.
This commit is contained in:
commit
e09af15085
328
README.md
Normal file
328
README.md
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
Gitea
|
||||||
|
=====
|
||||||
|
|
||||||
|
This role sets up and configures a [Gitea](https://gitea.io/) instance.
|
||||||
|
It supports official binaries from https://gitea.io/ or distribution-provided packages.
|
||||||
|
Local user accounts can be created on deployment.
|
||||||
|
It is also possible to configure external authentication sources.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
Gitea versions older than 1.18.0 are not (fully) supported.
|
||||||
|
Depending on the exact configuration, they may or may not work.
|
||||||
|
|
||||||
|
If TLS encryption (i.e. HTTPS) is desired, the target system needs to have a suitable X.509 certificate.
|
||||||
|
This roles does not handle deploying certificates.
|
||||||
|
|
||||||
|
Gitea needs a database server, unless it is configured to use SQLite.
|
||||||
|
This role does not handle database configuration.
|
||||||
|
|
||||||
|
Gitea's (optional) email system requires a SMTP server or a working `sendmail` program.
|
||||||
|
This is not set up by this role either.
|
||||||
|
|
||||||
|
Role Variables
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* `gitea_use_pkg`
|
||||||
|
Whether to prefer the distribution's package of Gitea.
|
||||||
|
Defaults to `true` but is set to `false` if the distribution is not known provide a package.
|
||||||
|
* `gitea_version`
|
||||||
|
What version of Gitea to install from <https://gitea.io/>.
|
||||||
|
If left unset, the latest version (not including release candidates) is chosen.
|
||||||
|
This setting is ignored when using a distribution package (cf. `gitea_use_pkg`).
|
||||||
|
* `gitea_bind_address`
|
||||||
|
The IP address to bind to.
|
||||||
|
Set to `0.0.0.0` to listen on all IP addresses.
|
||||||
|
Defaults to `127.0.0.1`.
|
||||||
|
* `gitea_port`
|
||||||
|
The TCP port to listen on.
|
||||||
|
Defaults to `443` if `gitea_tls_cert` is set and `80` if it is not.
|
||||||
|
* `gitea_tls_cert`
|
||||||
|
Path to a PEM-encoded X.509 certificate for Gitea to use.
|
||||||
|
The file needs to exist and be readable by the Gitea user.
|
||||||
|
Default is unset, which disables TLS support.
|
||||||
|
* `gitea_tls_cert_key`
|
||||||
|
Path to the PEM-encoded private key file for the certificate.
|
||||||
|
The file needs to exist and be readable by the Gitea user.
|
||||||
|
Default is unset.
|
||||||
|
* `gitea_user`, `gitea_group`
|
||||||
|
The system user account and system group to run Gitea as.
|
||||||
|
`gitea_user` defaults to `git`; `gitea_group` defaults to the user name.
|
||||||
|
When using a distribution package (cf. `gitea_use_pkg`), these settings are ignored.
|
||||||
|
* `gitea_data_path`
|
||||||
|
The path where repositories, user avatars and similar data is stored.
|
||||||
|
Defaults to `/var/lib/gitea`.
|
||||||
|
* `gitea_log_path`
|
||||||
|
The directory where Gitea's log files are stored.
|
||||||
|
Gitea creates a number of log files for different purposes.
|
||||||
|
Defaults to `/var/log/gitea`.
|
||||||
|
* `gitea_loglevel`
|
||||||
|
The log level Gitea's various loggers.
|
||||||
|
Valid values are `Trace`, `Debug`, `Info`, `Warn`, `Error`, `Critical`, `Fatal` and `None` in decreasing order of verbosity.
|
||||||
|
Fine tuning individual loggers is possible using `gitea_extra_options`.
|
||||||
|
Defaults to `Info`.
|
||||||
|
* `gitea_custom_path`
|
||||||
|
The path where custom files can be placed.
|
||||||
|
These files allow [customizing Gitea](https://docs.gitea.io/en-us/customizing-gitea/).
|
||||||
|
`gitea_custom_files` can be used to deploy files to this path.
|
||||||
|
Note: For security reasons, setting this to a directory within `gitea_data_path` is not recommended.
|
||||||
|
Defaults to `/etc/gitea/custom`.
|
||||||
|
* `gitea_custom_files`
|
||||||
|
Path to a directory on the Ansible controller that contains files that should be deployed to `gitea_custom_path`.
|
||||||
|
Refer to the [Gitea documentation](https://docs.gitea.io/en-us/customizing-gitea/) for details.
|
||||||
|
Optional.
|
||||||
|
* `gitea_database_type`
|
||||||
|
The type of database that Gitea should use to store user information, repository metadata, issues, etc.
|
||||||
|
Valid values are `mysql`, `postgres`, `mssql` and `sqlite3`.
|
||||||
|
Note that this role does not set up a database for Gitea.
|
||||||
|
This should be done by another role, unless using SQLite, which does not need any setup.
|
||||||
|
Mandatory.
|
||||||
|
* `gitea_database_host`
|
||||||
|
The host name (and optionally port) of the database system.
|
||||||
|
This can also be an absolute path to a UNIX socket, if the database runs on the same system as Gitea.
|
||||||
|
Mandatory, unless `gitea_database_type` is `sqlite3`.
|
||||||
|
* `gitea_database_name`
|
||||||
|
The name of the database to use.
|
||||||
|
When using SQLite, this is the path to the database file.
|
||||||
|
If not set, Gitea's internal default value is used.
|
||||||
|
* `gitea_database_user`
|
||||||
|
User account to use when connecting to the database.
|
||||||
|
Mandatory, unless `gitea_database_type` is `sqlite3`.
|
||||||
|
* `gitea_database_password`
|
||||||
|
The password for `gitea_database_user`.
|
||||||
|
Omit, if the database does not require a password.
|
||||||
|
* `gitea_enable_mailer`
|
||||||
|
Whether to enable the mailer (for password resets, etc.) and email notifications.
|
||||||
|
Requires are working SMTP server, somewhere.
|
||||||
|
Setting up an SMTP server is outside the scope of this role.
|
||||||
|
Defaults to `false` unless `gitea_mailer_host` is set.
|
||||||
|
* `gitea_mailer_host`
|
||||||
|
The host name (and optionally port) of a SMTP server to use for sending email.
|
||||||
|
If the mailer is enabled without setting this option, the system's `sendmail` command is used.
|
||||||
|
Optional.
|
||||||
|
* `gitea_mailer_from`
|
||||||
|
The sender address for mail generated by Gitea in RFC 5322 format.
|
||||||
|
Mandatory if the mailer is enabled.
|
||||||
|
* `gitea_mailer_user`
|
||||||
|
User account to use when connecting to the SMTP server.
|
||||||
|
Optional.
|
||||||
|
* `gitea_mailer_password`
|
||||||
|
The password of `gitea_mailer_user`.
|
||||||
|
Optional.
|
||||||
|
* `gitea_enable_indexer`
|
||||||
|
Whether to enable the repository indexer.
|
||||||
|
The indexer provides code search, but is known to use a fairly large amount of disk space.
|
||||||
|
Defaults to `true`.
|
||||||
|
* `gitea_enable_lfs`
|
||||||
|
Whether to enable git-lfs support for storing large file more efficiently.
|
||||||
|
Defaults to `false`.
|
||||||
|
* `gitea_enable_signing`
|
||||||
|
Whether to enable automatic singing of commits that are created via the web interface (e.g. on merges or repository initialisation).
|
||||||
|
For this purpose a PGP key is generated and stored on the remote system.
|
||||||
|
Note that a key is generated only once, and not regenerated, e.g. when the configured identity or other key parameters are changed.
|
||||||
|
The exact conditions on when a signature is made can be fine tuned using `gitea_extra_options`.
|
||||||
|
Defaults to `true`.
|
||||||
|
* `gitea_signing_key_type`
|
||||||
|
The type of PGP key to generate.
|
||||||
|
Valid values depend on the capabilities of the `gpg` program on the remote system.
|
||||||
|
Defaults to `RSA`.
|
||||||
|
* `gitea_signing_key_length`
|
||||||
|
Length of the PGP key in bits.
|
||||||
|
Defaults to `4096`.
|
||||||
|
* `gitea_committer_name`
|
||||||
|
If `gitea_enable_signing` is `true`, this is the name in the signing PGP key.
|
||||||
|
The value may be used elsewhere as well.
|
||||||
|
Defaults to `Gitea Bot`.
|
||||||
|
* `gitea_committer_email`
|
||||||
|
If `gitea_enable_signing` is `true`, this is the email address in the signing PGP key.
|
||||||
|
The value may be used elsewhere as well.
|
||||||
|
The email address does not need to exist.
|
||||||
|
Defaults to `invalid`.
|
||||||
|
Another generically useful value might be `{{ gitea_user }}@{{ ansible_facts['hostname'] }}`.
|
||||||
|
* `gitea_users`
|
||||||
|
A list of local user account to set up within Gitea.
|
||||||
|
Note that this only allows creating users, but not modifying existing users.
|
||||||
|
Each list item is in turn a dictionary with the following keys:
|
||||||
|
* `name`
|
||||||
|
The user's name.
|
||||||
|
Needs to be unique within the Gitea installation.
|
||||||
|
Mandatory.
|
||||||
|
* `email`
|
||||||
|
The user's email address.
|
||||||
|
Needs to be unique within the Gitea installation.
|
||||||
|
Mandatory.
|
||||||
|
* `password`
|
||||||
|
The user's password.
|
||||||
|
Mandatory.
|
||||||
|
* `admin`
|
||||||
|
Whether to assign administrative privileges to the user.
|
||||||
|
Defaults to `false`.
|
||||||
|
Note: `gitea_users` only works on Gitea 1.14.0 or newer.
|
||||||
|
* `gitea_auth_providers`
|
||||||
|
A list of [external authentication](https://docs.gitea.io/en-us/authentication/) sources to set up within Gitea.
|
||||||
|
Each list item is in turn a dictionary with the following keys:
|
||||||
|
* `name`
|
||||||
|
The name of the authentication source.
|
||||||
|
Needs to be unique within the Gitea installation.
|
||||||
|
Mandatory.
|
||||||
|
* `type`
|
||||||
|
The type of external authentication source to configure.
|
||||||
|
Valid values are `oauth`, `ldap` and `ldap-simple`.
|
||||||
|
Mandatory.
|
||||||
|
If `type` is `oauth`, the following keys are used:
|
||||||
|
* `provider`
|
||||||
|
The name of the OAuth2 provider.
|
||||||
|
Valid values are the names of providers supported by Gitea, such as `github`, `gitlab` or `twitter`.
|
||||||
|
Mandatory.
|
||||||
|
* `client_id`
|
||||||
|
The client ID for use with the OAuth2 provider.
|
||||||
|
Mandatory.
|
||||||
|
* `client_secret`
|
||||||
|
The client secret for use with the OAuth2 provider.
|
||||||
|
Mandatory.
|
||||||
|
* `auto_discover_url`
|
||||||
|
The OpenID auto discovery URL.
|
||||||
|
Optional.
|
||||||
|
* `use_custom_urls`
|
||||||
|
Whether to use custom URLs if `provider` is `github`, `gitlab` or `gitea`.
|
||||||
|
Defaults to `false`.
|
||||||
|
* `custom_tenant_id`
|
||||||
|
A custom Tenant ID for OAuth2 endpoint (cf. `use_custom_urls`).
|
||||||
|
Optional.
|
||||||
|
Only works on Gitea 1.19.0 an newer.
|
||||||
|
* `custom_auth_url`
|
||||||
|
A custom Authorization URL (cf. `use_custom_urls`).
|
||||||
|
Optional.
|
||||||
|
* `custom_email_url`
|
||||||
|
A custom Email URL (cf. `use_custom_urls`).
|
||||||
|
Optional.
|
||||||
|
* `custom_profile_url`
|
||||||
|
A custom Profile URL (cf. `use_custom_urls`).
|
||||||
|
Optional.
|
||||||
|
* `custom_token_url`
|
||||||
|
A custom Token URL (cf. `use_custom_urls`).
|
||||||
|
Optional.
|
||||||
|
If `type` is `ldap` or `ldap-simple`, the following keys are used:
|
||||||
|
* `host`
|
||||||
|
The host name of the LDAP server to connect to.
|
||||||
|
Mandatory.
|
||||||
|
* `port`
|
||||||
|
The TCP port the LDAP service runs on.
|
||||||
|
Defaults to `389` or, if `encryption` is `ldaps`, to `636`.
|
||||||
|
* `encryption`
|
||||||
|
How connections to the LDAP server should be encrypted.
|
||||||
|
Valid values are `disable`, `starttls` and `ldaps`.
|
||||||
|
Mandatory.
|
||||||
|
* `bind_dn`
|
||||||
|
If `type` is `ldap`: The DN to bind to the LDAP server with when searching for the user. Omit to perform an anonymous search.
|
||||||
|
If `type` is `ldap-simple`: A template to use as the user's DN. `%s` is substituted with the login name given on sign-in form.
|
||||||
|
Mandatory if `type` is `ldap-simple`.
|
||||||
|
* `bind_password`
|
||||||
|
The password for the user in `bind_dn`.
|
||||||
|
Only used when `type` is `ldap`.
|
||||||
|
* `user_search_base`
|
||||||
|
The LDAP base at which user accounts will be searched for.
|
||||||
|
Mandatory if `type` is `ldap`.
|
||||||
|
* `user_filter`
|
||||||
|
An LDAP filter declaring when a user should be allowed to log in.
|
||||||
|
`%s` is substituted with login name given on sign-in form.
|
||||||
|
Mandatory.
|
||||||
|
* `admin_filter`
|
||||||
|
An LDAP filter specifying if a user should be given administrator privileges.
|
||||||
|
If a user account passes the filter, the user will be privileged as an administrator.
|
||||||
|
Optional.
|
||||||
|
* `username_attribute`
|
||||||
|
The attribute of the user's LDAP record containing the user name.
|
||||||
|
The attribute value will be used for new Gitea accounts' user name after the first successful sign-in.
|
||||||
|
Leave empty to use the login name given on sign-in form.
|
||||||
|
This is useful when the supplied login name is matched against multiple attributes, but only a single specific attribute should be used for the Gitea account name.
|
||||||
|
Optional.
|
||||||
|
* `email_attribute`
|
||||||
|
The attribute of the user's LDAP record containing the user's email address.
|
||||||
|
Defaults to `mail`.
|
||||||
|
* `firstname_attribute`
|
||||||
|
The attribute of the user's LDAP record containing the user's first name.
|
||||||
|
Optional.
|
||||||
|
* `surname_attribute`
|
||||||
|
The attribute of the user's LDAP record containing the user's surname.
|
||||||
|
Optional.
|
||||||
|
* `sshkey_attribute`
|
||||||
|
The attribute of the user's LDAP record containing the user's public SSH key.
|
||||||
|
Optional.
|
||||||
|
* `sync_users`
|
||||||
|
This option enables a periodic task that synchronizes the Gitea users with the LDAP server.
|
||||||
|
Defaults to `false`.
|
||||||
|
Note: `gitea_auth_providers` only works on Gitea 1.12.0 or newer.
|
||||||
|
* `gitea_extra_options`
|
||||||
|
Additional configuration options for Gitea.
|
||||||
|
This variable is a dictionary where the keys are section names in `app.ini`.
|
||||||
|
The values are in turn dictionaries where keys are Gitea configuration options for the appropriate section and values are the corresponding configuration values.
|
||||||
|
Refer to the [Gitea documentation](https://docs.gitea.io/en-us/config-cheat-sheet/) for options and their meaning.
|
||||||
|
Optional.
|
||||||
|
* `gitea_extra_groups`
|
||||||
|
A list of groups that the Gitea system user is added to.
|
||||||
|
This allows granting access to additional resources, such as the private key file.
|
||||||
|
All groups need to exist on the target system; this role does not create them.
|
||||||
|
Empty by default.
|
||||||
|
* `gitea_inaccessible_paths`
|
||||||
|
If the target system uses systemd, this option takes a list of paths, that should not be accessible at all for Gitea.
|
||||||
|
Regardless of this option, home directories are made inaccessible.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
This role does not set up TLS certificates and therefore depends on a role that generates and deploys them, if TLS support is desired.
|
||||||
|
|
||||||
|
It also depends on a role to set up a MySQL/MariaDB, PostgreSQL or Microsoft SQL Server, respectively (possibly on a different system), if using a "full" DBMS is desired.
|
||||||
|
Alternatively, SQLite can be used, which does not require any further setup.
|
||||||
|
|
||||||
|
Example Configuration
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The following is a short example for some of the configuration options this role provides:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
gitea_bind_address: '0.0.0.0'
|
||||||
|
gitea_database_type: 'mysql'
|
||||||
|
gitea_database_host: '/run/mysqld/mysqld.sock'
|
||||||
|
gitea_database_name: 'gitea'
|
||||||
|
gitea_database_user: 'git'
|
||||||
|
gitea_inaccessible_paths:
|
||||||
|
- '/var/lib/mysql'
|
||||||
|
gitea_enable_mailer: true
|
||||||
|
gitea_mailer_from: "{{ gitea_user }}@{{ ansible_facts['fqdn'] }}"
|
||||||
|
gitea_extra_options:
|
||||||
|
server:
|
||||||
|
LANDING_PAGE: 'explore'
|
||||||
|
service:
|
||||||
|
DISABLE_REGISTRATION: true
|
||||||
|
gitea_users:
|
||||||
|
- name: 'admin user'
|
||||||
|
email: 'admin@my.domain'
|
||||||
|
password: 'admin_password'
|
||||||
|
admin: true
|
||||||
|
- name: 'ordinary user'
|
||||||
|
email: 'user@my.domain'
|
||||||
|
password: 'user_password'
|
||||||
|
gitea_auth_providers:
|
||||||
|
- name: 'OpenLDAP'
|
||||||
|
type: 'ldap'
|
||||||
|
host: 'localhost'
|
||||||
|
encryption: 'disable'
|
||||||
|
bind_dn: 'cn=gitea,ou=machines,dc=my,dc=domain'
|
||||||
|
bind_password: 'some_password'
|
||||||
|
user_search_base: 'ou=people,dc=my,dc=domain'
|
||||||
|
user_filter: '(&(objectClass=posixAccount)(uid=%s))'
|
||||||
|
admin_filter: '(memberOf=cn=Gitea Admins,ou=groups,dc=my,dc=domain)'
|
||||||
|
username_attribute: 'uid'
|
||||||
|
email_attribute: 'mail'
|
||||||
|
sshkey_attribute: 'sshPublicKey'
|
||||||
|
sync_users: true
|
||||||
|
```
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
MIT
|
||||||
23
defaults/main.yml
Normal file
23
defaults/main.yml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
gitea_use_pkg: true
|
||||||
|
gitea_user: 'git'
|
||||||
|
gitea_group: "{{ gitea_user }}"
|
||||||
|
gitea_extra_groups: []
|
||||||
|
gitea_data_path: '/var/lib/gitea'
|
||||||
|
gitea_log_path: '/var/log/gitea'
|
||||||
|
gitea_custom_path: "/etc/gitea/custom"
|
||||||
|
gitea_inaccessible_paths: []
|
||||||
|
gitea_bind_address: '127.0.0.1'
|
||||||
|
gitea_port: "{{ (gitea_tls_cert is defined) | ternary(443, 80) }}"
|
||||||
|
gitea_loglevel: 'Info'
|
||||||
|
gitea_enable_mailer: "{{ gitea_mailer_host is defined }}"
|
||||||
|
gitea_enable_lfs: false
|
||||||
|
gitea_enable_indexer: true
|
||||||
|
gitea_enable_signing: true
|
||||||
|
gitea_committer_name: 'Gitea Bot'
|
||||||
|
gitea_committer_email: 'invalid'
|
||||||
|
gitea_signing_key_type: 'RSA'
|
||||||
|
gitea_signing_key_length: 4096
|
||||||
|
gitea_extra_options: {}
|
||||||
|
gitea_users: []
|
||||||
|
gitea_auth_providers: []
|
||||||
15
filter_plugins/filters.py
Executable file
15
filter_plugins/filters.py
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'sort_versions': self.sort_versions,
|
||||||
|
}
|
||||||
|
|
||||||
|
def sort_versions(self, value):
|
||||||
|
"""This is a somewhat naive approach to version sorting. It only
|
||||||
|
supports versions that consist of numbers separated by dots."""
|
||||||
|
return sorted(value, key=lambda s: list(map(int, s.split('.'))))
|
||||||
19
handlers/main.yml
Normal file
19
handlers/main.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
- name: 'reload service files'
|
||||||
|
systemd:
|
||||||
|
daemon_reload: true
|
||||||
|
listen: gitea_reload_service_files
|
||||||
|
when: "ansible_facts['service_mgr'] == 'systemd'"
|
||||||
|
|
||||||
|
- name: 'remove temporary directory'
|
||||||
|
file:
|
||||||
|
path: "{{ _tmpdir.path }}"
|
||||||
|
state: absent
|
||||||
|
diff: false
|
||||||
|
listen: 'gitea_remove_tmpdir'
|
||||||
|
|
||||||
|
- name: 'restart gitea'
|
||||||
|
service:
|
||||||
|
name: 'gitea'
|
||||||
|
enabled: true
|
||||||
|
state: "{{ ansible_facts['is_chroot'] | ternary(omit, 'restarted') }}"
|
||||||
547
library/gitea_auth.py
Executable file
547
library/gitea_auth.py
Executable file
@ -0,0 +1,547 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2020, Sebastian Hamann
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {
|
||||||
|
'metadata_version': '1.1',
|
||||||
|
'status': ['preview'],
|
||||||
|
'supported_by': 'community'
|
||||||
|
}
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
---
|
||||||
|
module: gitea_auth
|
||||||
|
|
||||||
|
short_description: Manage external authentication sources in Gitea
|
||||||
|
|
||||||
|
version_added: none
|
||||||
|
|
||||||
|
description:
|
||||||
|
- "The `gitea_auth` module allows adding, updating and removing external
|
||||||
|
authentication sources in an instance of Gitea."
|
||||||
|
|
||||||
|
requirements:
|
||||||
|
- Gitea >= 1.12.0
|
||||||
|
|
||||||
|
notes:
|
||||||
|
- Many options are required when adding new authentication sources. If the authentication source named as in I(name) already exists, the required options can be omitted.
|
||||||
|
- If I(state) is C(present), this module always reports a changed result, since Gitea does not currently provide full information about configured authentication sources.
|
||||||
|
|
||||||
|
options:
|
||||||
|
admin_filter:
|
||||||
|
description:
|
||||||
|
- An LDAP filter specifying if a user should be given administrator privileges. If a user account passes the filter, the user will be privileged as an administrator.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
auto_discover_url:
|
||||||
|
description:
|
||||||
|
- OpenID Connect auto discovery URL
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
bind_dn:
|
||||||
|
description:
|
||||||
|
- If I(type) is C(ldap): The DN to bind to the LDAP server with when searching for the user. Omit to perform an anonymous search.
|
||||||
|
- If I(type) is C(ldap-simple): A template to use as the user's DN. The %s matching parameter will be substituted with the login name given on sign-in form.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
- Required if I(type) is C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
bind_password:
|
||||||
|
description:
|
||||||
|
- The password for the Bind DN specified above, if any.
|
||||||
|
- Note: The password is stored in plaintext on the server. As such, ensure that the Bind DN has as few privileges as possible.
|
||||||
|
- Only used if I(type) is C(ldap) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
client_id:
|
||||||
|
description:
|
||||||
|
- OAuth2 Client ID
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
- Required in this case.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
client_secret:
|
||||||
|
description:
|
||||||
|
- OAuth2 Client secret
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
- Required in this case.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
config:
|
||||||
|
description:
|
||||||
|
- Path to the Gitea config file (C(app.ini)).
|
||||||
|
- The config file must contain the C(RUN_USER) setting.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
default: /etc/gitea/app.ini
|
||||||
|
custom_tenant_id:
|
||||||
|
description:
|
||||||
|
- Use custom Tenant ID for OAuth endpoints
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
custom_auth_url:
|
||||||
|
description:
|
||||||
|
- Use a custom Authorization URL (option for GitLab/GitHub).
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
custom_email_url:
|
||||||
|
description:
|
||||||
|
- Use a custom Email URL (option for GitHub).
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
custom_profile_url:
|
||||||
|
description:
|
||||||
|
- Use a custom Profile URL (option for GitLab/GitHub).
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
custom_token_url:
|
||||||
|
description:
|
||||||
|
- Use a custom Token URL (option for GitLab/GitHub).
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
email_attribute:
|
||||||
|
description:
|
||||||
|
- The attribute of the user's LDAP record containing the user's email address.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
encryption:
|
||||||
|
description:
|
||||||
|
- Whether and how to use TLS when connecting to the LDAP server.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
- Required in this case.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
choices: ['disable', 'starttls', 'ldaps']
|
||||||
|
firstname_attribute:
|
||||||
|
description:
|
||||||
|
- The attribute of the user's LDAP record containing the user's first name.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
host:
|
||||||
|
description:
|
||||||
|
- The host name of the LDAP server.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
- Required in this case.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
name:
|
||||||
|
description:
|
||||||
|
- The name of the external authentication source.
|
||||||
|
- The name needs to be unique in the Gitea installation.
|
||||||
|
type: str
|
||||||
|
required: True
|
||||||
|
port:
|
||||||
|
description:
|
||||||
|
- The port to use when connecting to the server.
|
||||||
|
- Default is 636 if I(encryption) is C(ldaps) and otherwise 389.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: int
|
||||||
|
required: False
|
||||||
|
provider:
|
||||||
|
description:
|
||||||
|
- The name of an OAuth2 provider supported by Gitea. Valid names include "github", "gitlab" or "twitter", for instance.
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
- Required in this case.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
sshkey_attribute:
|
||||||
|
description:
|
||||||
|
- The attribute of the user's LDAP record containing the user's public SSH key.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
state:
|
||||||
|
description:
|
||||||
|
- Whether the authentication source should exist or not, taking action if the state is different from what is stated.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
default: 'present'
|
||||||
|
choices: ['present', 'absent']
|
||||||
|
surname_attribute:
|
||||||
|
description:
|
||||||
|
- The attribute of the user's LDAP record containing the user's surname.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
sync_users:
|
||||||
|
description:
|
||||||
|
- This option enables a periodic task that synchronizes the Gitea users with the LDAP server.
|
||||||
|
- Only used if I(type) is C(ldap) and I(state) is C(present).
|
||||||
|
type: bool
|
||||||
|
required: False
|
||||||
|
default: False
|
||||||
|
type:
|
||||||
|
description:
|
||||||
|
- The type of external authentication provider to set up.
|
||||||
|
- Only used if I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
choices: ['oauth', 'ldap', 'ldap-simple']
|
||||||
|
use_custom_urls:
|
||||||
|
description:
|
||||||
|
- Whether to use custom URLs for GitLab/GitHub OAuth endpoints.
|
||||||
|
- Only used if I(type) is C(oauth) and I(state) is C(present).
|
||||||
|
type: bool
|
||||||
|
required: False
|
||||||
|
user_filter:
|
||||||
|
description:
|
||||||
|
- An LDAP filter declaring when a user should be allowed to log in. The %s matching parameter will be substituted with login name given on sign-in form.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
- Required in this case.
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
user_search_base:
|
||||||
|
description:
|
||||||
|
- The LDAP base at which user accounts will be searched for.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
- Required if I(type) is C(ldap) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
username_attribute:
|
||||||
|
description:
|
||||||
|
- The attribute of the user's LDAP record containing the user name. The attribute value will be used for new Gitea accounts' user name after the first successful sign-in. Leave empty to use the login name given on sign-in form.
|
||||||
|
- This is useful when the supplied login name is matched against multiple attributes, but only a single specific attribute should be used for the Gitea account name.
|
||||||
|
- Only used if I(type) is C(ldap) or C(ldap-simple) and I(state) is C(present).
|
||||||
|
type: str
|
||||||
|
required: False
|
||||||
|
|
||||||
|
author:
|
||||||
|
- Sebastian Hamann (@s-hamann)
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
# Create an OAuth2 authentication source
|
||||||
|
- name: Enable login with GitHub
|
||||||
|
gitea_auth:
|
||||||
|
name: GitHub
|
||||||
|
type: oauth
|
||||||
|
provider: github
|
||||||
|
client_id: gitea
|
||||||
|
client_secret: some_token
|
||||||
|
|
||||||
|
# Create an LDAP authentication source
|
||||||
|
- name: Enable LDAP login
|
||||||
|
gitea_auth:
|
||||||
|
name: OpenLDAP
|
||||||
|
type: ldap
|
||||||
|
host: ldap.my.domain
|
||||||
|
encryption: starttls
|
||||||
|
bind_dn: uid=gitea,ou=machines,dc=my,dc=domain
|
||||||
|
bind_password: some_password
|
||||||
|
user_search_base: ou=people,dc=my,dc=domain
|
||||||
|
user_filter: '(&(objectClass=posixAccount)(uid=%s)(memberOf=cn=Gitea Users,ou=groups,dc=my,dc=domain))'
|
||||||
|
admin_filter: '(memberOf=cn=Gitea Admins,ou=groups,dc=my,dc=domain)'
|
||||||
|
username_attribute: uid
|
||||||
|
firstname_attribute: givenName
|
||||||
|
surname_attribute: sn
|
||||||
|
email_attribute: mail
|
||||||
|
sshkey_attribute: sshPublicKey
|
||||||
|
sync_users: true
|
||||||
|
|
||||||
|
# Create an LDAP authentication source
|
||||||
|
- name: Enable Active Directory login
|
||||||
|
gitea_auth:
|
||||||
|
name: Active Directory
|
||||||
|
type: ldap
|
||||||
|
host: dc.my.domain
|
||||||
|
encryption: ldaps
|
||||||
|
bind_dn: uid=gitea,ou=machines,dc=my,dc=domain
|
||||||
|
bind_password: some_password
|
||||||
|
user_search_base: ou=people,dc=my,dc=domain
|
||||||
|
user_filter: '(&(objectCategory=Person)(memberOf=cn=Gitea Users,ou=groups,dc=my,dc=domain)(sAMAccountName=%s)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
|
||||||
|
admin_filter: '(memberOf=cn=Gitea Admins,ou=groups,dc=my,dc=domain)'
|
||||||
|
username_attribute: sAMAccountName
|
||||||
|
firstname_attribute: givenName
|
||||||
|
surname_attribute: sn
|
||||||
|
email_attribute: mail
|
||||||
|
sync_users: true
|
||||||
|
|
||||||
|
# Delete an authentication source
|
||||||
|
- name: Remove login with GitHub
|
||||||
|
gitea_auth:
|
||||||
|
name: GitHub
|
||||||
|
state: absent
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = '''
|
||||||
|
'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pwd
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
|
AuthSrc = namedtuple('AuthSrc', ['id', 'name', 'type', 'enabled'])
|
||||||
|
CommandResult = namedtuple('CommandResult', ['stdout', 'stderr', 'returncode'])
|
||||||
|
|
||||||
|
|
||||||
|
def gitea_cmd(command, app_ini_path):
|
||||||
|
"""Run the given Gitea auth command and return the output.
|
||||||
|
|
||||||
|
:command: The auth command to run, as a list (e.g. ['delete', '--id', '1'])
|
||||||
|
:app_ini_path: The absolute path to the configuration file (app.ini)
|
||||||
|
:returns: The output and return code of the given command as a named tuple
|
||||||
|
(stdout, stderr, returncode)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def become_gitea(uid, gid):
|
||||||
|
"""Return a function that changes the uid and gid to the given
|
||||||
|
user and group."""
|
||||||
|
def result():
|
||||||
|
os.setgroups([gid])
|
||||||
|
os.setgid(gid)
|
||||||
|
os.setuid(uid)
|
||||||
|
return result
|
||||||
|
|
||||||
|
import configparser
|
||||||
|
app_ini = configparser.ConfigParser()
|
||||||
|
app_ini.read(app_ini_path)
|
||||||
|
user = app_ini['DEFAULT']['RUN_USER']
|
||||||
|
|
||||||
|
userinfo = pwd.getpwnam(user)
|
||||||
|
uid = userinfo.pw_uid
|
||||||
|
gid = userinfo.pw_gid
|
||||||
|
home = userinfo.pw_dir
|
||||||
|
|
||||||
|
env = os.environ.copy()
|
||||||
|
env['HOME'] = home
|
||||||
|
|
||||||
|
cmd = subprocess.Popen(['gitea', '--config', app_ini_path, 'admin', 'auth'] + command,
|
||||||
|
preexec_fn=become_gitea(uid, gid), cwd=home, env=env,
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
(stdout, stderr) = cmd.communicate()
|
||||||
|
return CommandResult(stdout, stderr, cmd.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def run_module():
|
||||||
|
# define available arguments/parameters a user can pass to the module
|
||||||
|
module_args = dict(
|
||||||
|
admin_filter=dict(type='str'),
|
||||||
|
auto_discover_url=dict(type='str'),
|
||||||
|
bind_dn=dict(type='str'),
|
||||||
|
bind_password=dict(type='str', no_log=True),
|
||||||
|
client_id=dict(type='str'),
|
||||||
|
client_secret=dict(type='str', no_log=True),
|
||||||
|
config=dict(type='str', default='/etc/gitea/app.ini'),
|
||||||
|
custom_tenant_id=dict(type='str'),
|
||||||
|
custom_auth_url=dict(type='str'),
|
||||||
|
custom_email_url=dict(type='str'),
|
||||||
|
custom_profile_url=dict(type='str'),
|
||||||
|
custom_token_url=dict(type='str'),
|
||||||
|
email_attribute=dict(type='str'),
|
||||||
|
encryption=dict(type='str', choices=['disable', 'starttls', 'ldaps']),
|
||||||
|
firstname_attribute=dict(type='str'),
|
||||||
|
host=dict(type='str'),
|
||||||
|
name=dict(type='str', required=True),
|
||||||
|
port=dict(type='int'),
|
||||||
|
provider=dict(type='str'),
|
||||||
|
sshkey_attribute=dict(type='str'),
|
||||||
|
state=dict(type='str', default='present', choices=['present', 'absent']),
|
||||||
|
surname_attribute=dict(type='str'),
|
||||||
|
sync_users=dict(type='bool', default=False),
|
||||||
|
type=dict(type='str', choices=['oauth', 'ldap', 'ldap-simple']),
|
||||||
|
use_custom_urls=dict(type='bool'),
|
||||||
|
user_filter=dict(type='str'),
|
||||||
|
user_search_base=dict(type='str'),
|
||||||
|
username_attribute=dict(type='str')
|
||||||
|
)
|
||||||
|
|
||||||
|
# seed the result dict in the object
|
||||||
|
result = dict(
|
||||||
|
changed=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=module_args,
|
||||||
|
supports_check_mode=True
|
||||||
|
)
|
||||||
|
|
||||||
|
auth_providers = []
|
||||||
|
|
||||||
|
# Get the currently configured authentication sources.
|
||||||
|
header_pos = {}
|
||||||
|
for line in gitea_cmd(['list'], module.params['config'])[0].splitlines():
|
||||||
|
# Gitea may print random cruft before the actual information, i.e. the
|
||||||
|
# header may not be in the first line. Search it.
|
||||||
|
line = line.decode().split()
|
||||||
|
if not header_pos:
|
||||||
|
if line[0] == 'ID':
|
||||||
|
header_pos['id'] = line.index('ID')
|
||||||
|
header_pos['name'] = line.index('Name')
|
||||||
|
header_pos['type'] = line.index('Type')
|
||||||
|
header_pos['enabled'] = line.index('Enabled')
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
a = AuthSrc(id=int(line[header_pos['id']]),
|
||||||
|
name=line[header_pos['name']],
|
||||||
|
type=line[header_pos['type']],
|
||||||
|
enabled=line[header_pos['enabled']].lower() == 'true'
|
||||||
|
)
|
||||||
|
auth_providers.append(a)
|
||||||
|
|
||||||
|
# Set `id` to the ID of the authentication source with the given name, if any.
|
||||||
|
for p in auth_providers:
|
||||||
|
if p.name == module.params['name']:
|
||||||
|
id = p.id
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
id = None
|
||||||
|
|
||||||
|
# Sanity checks on the parameters.
|
||||||
|
if module.params['state'] == 'present' and not module.params['type']:
|
||||||
|
module.fail_json(rc=256, msg='type is required with state=present')
|
||||||
|
if module.params['state'] == 'present' and id is None:
|
||||||
|
if module.params['type'] == 'oauth':
|
||||||
|
required_params = ['provider', 'client_id', 'client_secret']
|
||||||
|
elif module.params['type'] == 'ldap':
|
||||||
|
required_params = ['host', 'encryption', 'user_filter', 'user_search_base']
|
||||||
|
elif module.params['type'] == 'ldap-simple':
|
||||||
|
required_params = ['host', 'encryption', 'user_filter', 'bind_dn']
|
||||||
|
missing_params = []
|
||||||
|
for p in required_params:
|
||||||
|
if module.params[p] is None:
|
||||||
|
missing_params.append(p)
|
||||||
|
if missing_params:
|
||||||
|
msg = ('The following parameters are required: {lst}'.
|
||||||
|
format(lst=', '.join(missing_params)))
|
||||||
|
module.fail_json(rc=256, msg=msg)
|
||||||
|
|
||||||
|
if module.params['state'] == 'absent' and id is not None:
|
||||||
|
# Delete an authentication source.
|
||||||
|
if not module.check_mode:
|
||||||
|
retval = gitea_cmd(['delete', '--id', str(id)], module.params['config'])
|
||||||
|
if retval.returncode > 0:
|
||||||
|
msg = ('Could not delete authentication source {name}'.
|
||||||
|
format(name=module.params['name']))
|
||||||
|
module.fail_json(msg=msg, stdout=retval.stdout, rc=retval.returncode, **result)
|
||||||
|
result['changed'] = True
|
||||||
|
|
||||||
|
elif module.params['state'] == 'present':
|
||||||
|
# Add/update an authentication source.
|
||||||
|
if module.params['type'] == 'oauth':
|
||||||
|
if id is None:
|
||||||
|
cmd = ['add-oauth']
|
||||||
|
else:
|
||||||
|
cmd = ['update-oauth', '--id', str(id)]
|
||||||
|
cmd += ['--name', module.params['name']]
|
||||||
|
if module.params['provider']:
|
||||||
|
cmd += ['--provider', module.params['provider']]
|
||||||
|
if module.params['client_id']:
|
||||||
|
cmd += ['--key', module.params['client_id']]
|
||||||
|
if module.params['client_secret']:
|
||||||
|
cmd += ['--secret', module.params['client_secret']]
|
||||||
|
if module.params['auto_discover_url']:
|
||||||
|
cmd += ['--auto-discover-url', module.params['auto_discover_url']]
|
||||||
|
if module.params['use_custom_urls']:
|
||||||
|
cmd += ['--use-custom-urls', str(module.params['use_custom_urls'])]
|
||||||
|
if module.params['custom_tenant_id']:
|
||||||
|
cmd += ['--custom-tenant-id', module.params['custom_tenant_id']]
|
||||||
|
if module.params['custom_auth_url']:
|
||||||
|
cmd += ['--custom-auth-url', module.params['custom_auth_url']]
|
||||||
|
if module.params['custom_token_url']:
|
||||||
|
cmd += ['--custom-token-url', module.params['custom_token_url']]
|
||||||
|
if module.params['custom_profile_url']:
|
||||||
|
cmd += ['--custom-profile-url', module.params['custom_profile_url']]
|
||||||
|
if module.params['custom_email_url']:
|
||||||
|
cmd += ['--custom-email-url', module.params['custom_email_url']]
|
||||||
|
|
||||||
|
elif module.params['type'] == 'ldap' or module.params['type'] == 'ldap-simple':
|
||||||
|
if module.params['type'] == 'ldap':
|
||||||
|
if id is None:
|
||||||
|
cmd = ['add-ldap']
|
||||||
|
else:
|
||||||
|
cmd = ['update-ldap', '--id', str(id)]
|
||||||
|
if module.params['bind_dn']:
|
||||||
|
cmd += ['--bind-dn', module.params['bind_dn']]
|
||||||
|
cmd += ['--attributes-in-bind']
|
||||||
|
if module.params['bind_password']:
|
||||||
|
cmd += ['--bind-password', module.params['bind_password']]
|
||||||
|
if module.params['sync_users']:
|
||||||
|
cmd += ['--synchronize-users']
|
||||||
|
|
||||||
|
elif module.params['type'] == 'ldap-simple':
|
||||||
|
if id is None:
|
||||||
|
cmd = ['add-ldap-simple']
|
||||||
|
else:
|
||||||
|
cmd = ['update-ldap-simple', '--id', str(id)]
|
||||||
|
if module.params['bind_dn']:
|
||||||
|
cmd += ['--user-dn', module.params['bind_dn']]
|
||||||
|
|
||||||
|
cmd += ['--name', module.params['name']]
|
||||||
|
if module.params['host']:
|
||||||
|
cmd += ['--host', module.params['host']]
|
||||||
|
if module.params['port']:
|
||||||
|
cmd += ['--port', module.params['port']]
|
||||||
|
elif id is None:
|
||||||
|
if module.params['encryption'] == 'ldaps':
|
||||||
|
port = '636'
|
||||||
|
else:
|
||||||
|
port = '389'
|
||||||
|
cmd += ['--port', port]
|
||||||
|
if module.params['encryption']:
|
||||||
|
if module.params['encryption'] == 'disable':
|
||||||
|
encryption = 'unencrypted'
|
||||||
|
elif module.params['encryption'] == 'starttls':
|
||||||
|
encryption = 'StartTLS'
|
||||||
|
elif module.params['encryption'] == 'ldaps':
|
||||||
|
encryption = 'LDAPS'
|
||||||
|
cmd += ['--security-protocol', encryption]
|
||||||
|
if module.params['user_search_base']:
|
||||||
|
cmd += ['--user-search-base', module.params['user_search_base']]
|
||||||
|
if module.params['user_filter']:
|
||||||
|
cmd += ['--user-filter', module.params['user_filter']]
|
||||||
|
if module.params['admin_filter']:
|
||||||
|
cmd += ['--admin-filter', module.params['admin_filter']]
|
||||||
|
if module.params['username_attribute']:
|
||||||
|
cmd += ['--username-attribute', module.params['username_attribute']]
|
||||||
|
if module.params['firstname_attribute']:
|
||||||
|
cmd += ['--firstname-attribute', module.params['firstname_attribute']]
|
||||||
|
if module.params['surname_attribute']:
|
||||||
|
cmd += ['--surname-attribute', module.params['surname_attribute']]
|
||||||
|
if module.params['email_attribute'] or id is None:
|
||||||
|
email_attribute = module.params['email_attribute']
|
||||||
|
if not email_attribute:
|
||||||
|
email_attribute = 'mail'
|
||||||
|
cmd += ['--email-attribute', email_attribute]
|
||||||
|
if module.params['sshkey_attribute']:
|
||||||
|
cmd += ['--public-ssh-key-attribute', module.params['sshkey_attribute']]
|
||||||
|
|
||||||
|
if not module.check_mode:
|
||||||
|
retval = gitea_cmd(cmd, module.params['config'])
|
||||||
|
if retval.returncode > 0:
|
||||||
|
if id is None:
|
||||||
|
verb = 'add'
|
||||||
|
else:
|
||||||
|
verb = 'update'
|
||||||
|
msg = ('Could not {verb} authentication source {name}'.
|
||||||
|
format(verb=verb, name=module.params['name']))
|
||||||
|
module.fail_json(msg=msg, stdout=retval.stdout, rc=retval.returncode, **result)
|
||||||
|
|
||||||
|
# We can not know if anything was changed, since we can not get the
|
||||||
|
# full configuration of an authentication source out of Gitea.
|
||||||
|
result['changed'] = True
|
||||||
|
|
||||||
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
run_module()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
28
meta/main.yml
Normal file
28
meta/main.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
galaxy_info:
|
||||||
|
author: Sebastian Hamann
|
||||||
|
description: Install and configure Gitea
|
||||||
|
|
||||||
|
license: MIT
|
||||||
|
|
||||||
|
min_ansible_version: 2.8
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: Gentoo
|
||||||
|
versions:
|
||||||
|
- any
|
||||||
|
- name: Debian
|
||||||
|
versions:
|
||||||
|
- buster
|
||||||
|
- name: Alpine
|
||||||
|
versions:
|
||||||
|
- any
|
||||||
|
- name: GenericLinux
|
||||||
|
versions:
|
||||||
|
- any
|
||||||
|
|
||||||
|
galaxy_tags:
|
||||||
|
- development
|
||||||
|
- git
|
||||||
|
- gitea
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
25
tasks/get_secrets.yml
Normal file
25
tasks/get_secrets.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
# This file extracts a secret from the config file. If it is not found, a new value is generated.
|
||||||
|
# In either case, the secret is made available in a variable for future reference.
|
||||||
|
# Needs:
|
||||||
|
# * _slurp_appini - base64-encoded contents of app.ini
|
||||||
|
# * secret - the name of the secret to handle
|
||||||
|
|
||||||
|
- name: "extract {{ secret }} from current config file"
|
||||||
|
set_fact:
|
||||||
|
_secret_value: "{{ _slurp_appini.content | b64decode | regex_search('(?<=' ~ secret ~ '\\s=\\s`).*(?=`)') }}"
|
||||||
|
no_log: true
|
||||||
|
when: "_slurp_appini is not skipped"
|
||||||
|
|
||||||
|
- name: "generate new {{ secret }}"
|
||||||
|
command: "gitea generate secret '{{ secret }}'"
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_facts['env']['PATH'] }}:/usr/local/bin"
|
||||||
|
register: _generate_secret
|
||||||
|
no_log: true
|
||||||
|
when: "not _secret_value | default(false)"
|
||||||
|
|
||||||
|
- name: "store new {{ secret }}"
|
||||||
|
set_fact:
|
||||||
|
'_{{ secret }}': "{{ _generate_secret.stdout | default(_secret_value) }}"
|
||||||
|
no_log: true
|
||||||
144
tasks/install_gitea_binary.yml
Normal file
144
tasks/install_gitea_binary.yml
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
---
|
||||||
|
# This file handles installing Gitea using the official binary release.
|
||||||
|
# This includes
|
||||||
|
# * installing dependencies using the package manager
|
||||||
|
# * getting the latest version
|
||||||
|
# * downloading the binary
|
||||||
|
# * validating the signature
|
||||||
|
# * installing the binary to the correct path
|
||||||
|
# * creating the necessary system user account
|
||||||
|
# * installing a systemd service file/OpenRC init script
|
||||||
|
|
||||||
|
- name: 'install dependencies'
|
||||||
|
package:
|
||||||
|
name: "{{ gitea_dependencies }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: 'get available versions of Gitea'
|
||||||
|
uri:
|
||||||
|
url: "{{ gitea_base_url }}"
|
||||||
|
return_content: true
|
||||||
|
register: _gitea_downloads
|
||||||
|
|
||||||
|
- name: 'determine latest version of Gitea'
|
||||||
|
set_fact:
|
||||||
|
gitea_version: "{{ _gitea_downloads.content | regex_findall('(?<=/gitea/)[0-9]+\\.[0-9]+\\.[0-9]+') | sort_versions | last }}"
|
||||||
|
|
||||||
|
when: "gitea_version is not defined"
|
||||||
|
|
||||||
|
- name: 'get currently installed version of Gitea'
|
||||||
|
command: '/usr/local/bin/gitea --version'
|
||||||
|
check_mode: false
|
||||||
|
changed_when: false
|
||||||
|
ignore_errors: true
|
||||||
|
register: _gitea_version
|
||||||
|
|
||||||
|
- name: 'determine version number'
|
||||||
|
set_fact:
|
||||||
|
_current_gitea_version: "{{ _gitea_version.stdout | default('') | regex_search('(?<=Gitea version )[0-9.]+(-rc[0-9]+)?(?= )') }}"
|
||||||
|
|
||||||
|
- name: "download and install Gitea {{ gitea_version }}"
|
||||||
|
block:
|
||||||
|
|
||||||
|
- name: 'create temporary directory'
|
||||||
|
tempfile:
|
||||||
|
state: directory
|
||||||
|
diff: false
|
||||||
|
register: _tmpdir
|
||||||
|
notify: 'gitea_remove_tmpdir'
|
||||||
|
|
||||||
|
- name: 'determine file name'
|
||||||
|
set_fact:
|
||||||
|
_filename: "gitea-{{ gitea_version }}-linux-{{ gitea_arch }}"
|
||||||
|
|
||||||
|
- name: 'download gitea'
|
||||||
|
get_url:
|
||||||
|
url: "{{ gitea_base_url | regex_replace('/*$', '') }}/{{ gitea_version }}/{{ filename }}"
|
||||||
|
dest: "{{ _tmpdir.path }}"
|
||||||
|
loop:
|
||||||
|
- "{{ _filename }}"
|
||||||
|
- "{{ _filename }}.asc"
|
||||||
|
loop_control:
|
||||||
|
loop_var: filename
|
||||||
|
|
||||||
|
- name: 'create temporary GnuPG directory'
|
||||||
|
file:
|
||||||
|
path: "{{ _tmpdir.path }}/.gnupg"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0700
|
||||||
|
diff: false
|
||||||
|
|
||||||
|
- name: 'get the PGP keys'
|
||||||
|
command: "gpg --keyserver hkps://keys.openpgp.org --no-default-keyring --keyring trustedkeys.kbx --recv-key {{ gitea_pgp_fingerprint | quote }}"
|
||||||
|
environment:
|
||||||
|
GNUPGHOME: "{{ _tmpdir.path }}/.gnupg"
|
||||||
|
register: '_gpg_recv_key'
|
||||||
|
changed_when: "_gpg_recv_key is not failed and 'imported:' in _gpg_recv_key.stderr"
|
||||||
|
|
||||||
|
- name: 'verify signature'
|
||||||
|
command: "gpgv '{{ _tmpdir.path }}/{{ _filename }}.asc' '{{ _tmpdir.path }}/{{ _filename }}'"
|
||||||
|
environment:
|
||||||
|
GNUPGHOME: "{{ _tmpdir.path }}/.gnupg"
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: 'install gitea'
|
||||||
|
copy:
|
||||||
|
dest: '/usr/local/bin/gitea'
|
||||||
|
src: "{{ _tmpdir.path }}/{{ _filename }}"
|
||||||
|
remote_src: true
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0755
|
||||||
|
notify: 'restart gitea'
|
||||||
|
|
||||||
|
when: "gitea_version != _current_gitea_version"
|
||||||
|
|
||||||
|
- name: 'create Gitea system user group'
|
||||||
|
group:
|
||||||
|
name: "{{ gitea_group }}"
|
||||||
|
system: true
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: 'create Gitea system user account'
|
||||||
|
user:
|
||||||
|
name: "{{ gitea_user }}"
|
||||||
|
password: '*'
|
||||||
|
group: "{{ gitea_group }}"
|
||||||
|
home: "{{ gitea_data_path }}"
|
||||||
|
comment: 'Gitea service account'
|
||||||
|
shell: '/bin/sh'
|
||||||
|
system: true
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: 'check for MariaDB (systemd)'
|
||||||
|
stat:
|
||||||
|
path: '/lib/systemd/system/mariadb.service'
|
||||||
|
register: _mariadb_service
|
||||||
|
when: "gitea_database_type == 'mysql' and ansible_facts['service_mgr'] == 'systemd'"
|
||||||
|
|
||||||
|
- name: 'check for MariaDB (non-systemd)'
|
||||||
|
stat:
|
||||||
|
path: '/etc/init.d/mariadb'
|
||||||
|
register: _initd_mariadb
|
||||||
|
when: "gitea_database_type == 'mysql' and ansible_facts['service_mgr'] != 'systemd'"
|
||||||
|
|
||||||
|
- name: 'install systemd service file'
|
||||||
|
template:
|
||||||
|
dest: '/etc/systemd/system/gitea.service'
|
||||||
|
src: 'gitea.service.j2'
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0644
|
||||||
|
when: "ansible_facts['service_mgr'] == 'systemd'"
|
||||||
|
|
||||||
|
- name: 'install OpenRC init script'
|
||||||
|
template:
|
||||||
|
dest: '/etc/init.d/gitea'
|
||||||
|
src: 'gitea.openrc.j2'
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0755
|
||||||
|
when: "ansible_facts['service_mgr'] == 'openrc'"
|
||||||
266
tasks/main.yml
Normal file
266
tasks/main.yml
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
---
|
||||||
|
- name: 'gather os specific variables'
|
||||||
|
include_vars: "{{ vars_file }}"
|
||||||
|
loop:
|
||||||
|
- 'default.yml'
|
||||||
|
- "{{ ansible_facts['os_family'] | lower }}.yml"
|
||||||
|
- "{{ ansible_facts['distribution'] | lower }}.yml"
|
||||||
|
- "{{ ansible_facts['distribution'] | lower }}-{{ ansible_facts['distribution_major_version'] }}.yml"
|
||||||
|
- "{{ ansible_facts['distribution'] | lower }}-{{ ansible_facts['distribution_version'] }}.yml"
|
||||||
|
loop_control:
|
||||||
|
loop_var: vars_file
|
||||||
|
when: "(vars_file is abs and vars_file is file) or (vars_file is not abs and (role_path ~ '/vars/' ~ vars_file) is file)"
|
||||||
|
|
||||||
|
- name: 'check for bash'
|
||||||
|
stat:
|
||||||
|
path: '/bin/bash'
|
||||||
|
register: _bin_bash
|
||||||
|
|
||||||
|
- name: 'ensure configuration consistency'
|
||||||
|
set_fact:
|
||||||
|
gitea_use_pkg: "{{ gitea_has_pkg | bool and gitea_use_pkg | bool }}"
|
||||||
|
|
||||||
|
- name: 'set user name to distribution package value'
|
||||||
|
set_fact:
|
||||||
|
gitea_user: "{{ gitea_pkg_user }}"
|
||||||
|
gitea_group: "{{ gitea_pkg_group }}"
|
||||||
|
when: "gitea_use_pkg | bool"
|
||||||
|
|
||||||
|
- name: 'install Gitea using the package manager'
|
||||||
|
package:
|
||||||
|
name: "{{ gitea_pkg_name }}"
|
||||||
|
state: present
|
||||||
|
notify: 'restart gitea'
|
||||||
|
when: "gitea_use_pkg | bool"
|
||||||
|
|
||||||
|
- name: 'install Gitea from binary'
|
||||||
|
include_tasks: install_gitea_binary.yml
|
||||||
|
when: "not gitea_use_pkg | bool"
|
||||||
|
|
||||||
|
- name: 'install additional dependencies'
|
||||||
|
package:
|
||||||
|
name: "{{ pkg.pkg }}"
|
||||||
|
state: present
|
||||||
|
when: "pkg.when"
|
||||||
|
loop:
|
||||||
|
- pkg: 'git-lfs'
|
||||||
|
when: "{{ gitea_enable_lfs | bool }}"
|
||||||
|
- pkg: "{{ gitea_gnupg_package }}"
|
||||||
|
when: "{{ gitea_enable_signing | bool }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: 'pkg'
|
||||||
|
label: "{{ pkg.pkg }}"
|
||||||
|
|
||||||
|
- name: "add {{ gitea_user }} to extra groups"
|
||||||
|
user:
|
||||||
|
name: "{{ gitea_user }}"
|
||||||
|
groups: "{{ gitea_extra_groups }}"
|
||||||
|
append: true
|
||||||
|
notify: 'restart gitea'
|
||||||
|
when: "[gitea_extra_groups | default([])] | flatten | count"
|
||||||
|
|
||||||
|
- name: "harden gitea.service"
|
||||||
|
block:
|
||||||
|
- name: "create override directory for gitea.service"
|
||||||
|
file:
|
||||||
|
path: '/etc/systemd/system/gitea.service.d/'
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0755
|
||||||
|
|
||||||
|
- name: "install override file for gitea.service"
|
||||||
|
template:
|
||||||
|
dest: '/etc/systemd/system/gitea.service.d/override.conf'
|
||||||
|
src: 'gitea_override.conf.j2'
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0644
|
||||||
|
notify:
|
||||||
|
- 'gitea_reload_service_files'
|
||||||
|
- 'restart gitea'
|
||||||
|
|
||||||
|
when: "ansible_facts['service_mgr'] == 'systemd'"
|
||||||
|
|
||||||
|
- name: 'allow non-root users to bind to low ports'
|
||||||
|
sysctl:
|
||||||
|
name: 'net.ipv4.ip_unprivileged_port_start'
|
||||||
|
value: '0'
|
||||||
|
sysctl_file: '/etc/sysctl.d/unprivileged_ports.conf'
|
||||||
|
state: present
|
||||||
|
when: "ansible_facts['service_mgr'] != 'systemd' and gitea_port | int < 1024"
|
||||||
|
|
||||||
|
- name: 'check if Gitea is already configured'
|
||||||
|
stat:
|
||||||
|
path: '/etc/gitea/app.ini'
|
||||||
|
register: _stat_appini
|
||||||
|
|
||||||
|
- name: 'read current config file'
|
||||||
|
slurp:
|
||||||
|
src: '/etc/gitea/app.ini'
|
||||||
|
register: _slurp_appini
|
||||||
|
when: "_stat_appini.stat.exists"
|
||||||
|
|
||||||
|
- include_tasks: get_secrets.yml
|
||||||
|
loop:
|
||||||
|
- 'SECRET_KEY'
|
||||||
|
- 'INTERNAL_TOKEN'
|
||||||
|
- 'JWT_SECRET'
|
||||||
|
- 'LFS_JWT_SECRET'
|
||||||
|
loop_control:
|
||||||
|
loop_var: secret
|
||||||
|
|
||||||
|
- name: 'combine default and custom options'
|
||||||
|
set_fact:
|
||||||
|
_gitea_options: "{{ gitea_default_options | combine(gitea_extra_options, recursive=True) }}"
|
||||||
|
|
||||||
|
- name: 'create required directories'
|
||||||
|
file:
|
||||||
|
path: "{{ directory.path }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ directory.owner | default(gitea_user) }}"
|
||||||
|
group: "{{ directory.group | default(gitea_group) }}"
|
||||||
|
mode: "{{ directory.mode | default('0750') }}"
|
||||||
|
loop:
|
||||||
|
- path: '/etc/gitea'
|
||||||
|
owner: root
|
||||||
|
- path: "{{ gitea_data_path }}"
|
||||||
|
- path: "{{ _gitea_options['git']['HOME_PATH'] }}"
|
||||||
|
- path: "{{ gitea_custom_path }}"
|
||||||
|
owner: root
|
||||||
|
- path: "{{ gitea_log_path }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: directory
|
||||||
|
label: "{{ directory.path }}"
|
||||||
|
|
||||||
|
- name: 'configure Gitea'
|
||||||
|
template:
|
||||||
|
dest: '/etc/gitea/app.ini'
|
||||||
|
src: 'app.ini.j2'
|
||||||
|
owner: root
|
||||||
|
group: "{{ gitea_group }}"
|
||||||
|
mode: 0640
|
||||||
|
no_log: true
|
||||||
|
notify: 'restart gitea'
|
||||||
|
|
||||||
|
- name: 'unset secrets'
|
||||||
|
set_fact:
|
||||||
|
_slurp_appini:
|
||||||
|
_secret_value:
|
||||||
|
_generate_secret:
|
||||||
|
_SECRET_KEY:
|
||||||
|
_INTERNAL_TOKEN:
|
||||||
|
_JWT_SECRET:
|
||||||
|
_LFS_JWT_SECRET:
|
||||||
|
|
||||||
|
- name: 'create server-side commit signing key'
|
||||||
|
command: "su {{ gitea_user }} -c 'gpg --batch --generate-key'"
|
||||||
|
args:
|
||||||
|
warn: false # su is needed, otherwise Ansible might require a password to become the gitea user
|
||||||
|
creates: "{{ _gitea_options['git']['HOME_PATH'] }}/.gnupg/private-keys-v1.d/"
|
||||||
|
stdin: |
|
||||||
|
%no-protection
|
||||||
|
Key-Type: {{ gitea_signing_key_type }}
|
||||||
|
Key-Length: {{ gitea_signing_key_length }}
|
||||||
|
Key-Usage: sign
|
||||||
|
Name-Real: {{ gitea_committer_name }}
|
||||||
|
Name-Email: {{ gitea_committer_email }}
|
||||||
|
# Discard the time, use only the date as the creation timestamp
|
||||||
|
Creation-Date: {{ lookup('pipe', 'date +%Y-%m-%d') }}
|
||||||
|
when: "gitea_enable_signing | bool"
|
||||||
|
|
||||||
|
- name: 'configure git command line client'
|
||||||
|
ini_file:
|
||||||
|
path: "{{ _gitea_options['git']['HOME_PATH'] }}/.gitconfig"
|
||||||
|
section: "{{ item.section }}"
|
||||||
|
option: "{{ item.option }}"
|
||||||
|
value: "{{ item.value }}"
|
||||||
|
state: present
|
||||||
|
loop:
|
||||||
|
- section: 'commit'
|
||||||
|
option: 'gpgsign'
|
||||||
|
value: "{{ gitea_enable_signing | bool | string | lower }}"
|
||||||
|
- section: 'user'
|
||||||
|
option: 'name'
|
||||||
|
value: "{{ gitea_committer_name }}"
|
||||||
|
- section: 'user'
|
||||||
|
option: 'email'
|
||||||
|
value: "{{ gitea_committer_email }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.section }}.{{ item.option }} = {{ item.value }}"
|
||||||
|
|
||||||
|
- name: 'initialise gitea database (this may take a long time)'
|
||||||
|
command: "su {{ gitea_user }} -c 'PATH=\"{{ ansible_facts['env']['PATH'] }}:/usr/local/bin\" gitea -c /etc/gitea/app.ini migrate'"
|
||||||
|
args:
|
||||||
|
chdir: "{{ gitea_data_path }}"
|
||||||
|
warn: false # su is needed, otherwise Ansible might require a password to become the gitea user
|
||||||
|
|
||||||
|
- name: 'create initial local user accounts'
|
||||||
|
command: "su {{ gitea_user }} -c 'PATH=\"{{ ansible_facts['env']['PATH'] }}:/usr/local/bin\" gitea -c /etc/gitea/app.ini admin user create --username {{ user.name | quote }} --password {{ user.password | quote }} --email {{ user.email | quote }} {{ user.admin | default(false) | bool | ternary('--admin', '') }}'"
|
||||||
|
args:
|
||||||
|
chdir: "{{ gitea_data_path }}"
|
||||||
|
warn: false # su is needed, otherwise Ansible might require a password to become the gitea user
|
||||||
|
register: _create_user
|
||||||
|
failed_when: "_create_user.rc > 0 and 'user already exists' not in _create_user.stdout"
|
||||||
|
changed_when: "'New user ''' ~ user.name ~ ''' has been successfully created' in _create_user.stdout"
|
||||||
|
no_log: true
|
||||||
|
loop: "{{ gitea_users }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: user
|
||||||
|
label: "{{ user.name }}"
|
||||||
|
|
||||||
|
- name: 'configure external authentication sources'
|
||||||
|
gitea_auth:
|
||||||
|
name: "{{ provider.name }}"
|
||||||
|
type: "{{ provider.type }}"
|
||||||
|
host: "{{ provider.host | default(omit) }}"
|
||||||
|
port: "{{ provider.port | default(omit) }}"
|
||||||
|
encryption: "{{ provider.encryption | default(omit) }}"
|
||||||
|
bind_dn: "{{ provider.bind_dn | default(omit) }}"
|
||||||
|
bind_password: "{{ provider.bind_password | default(omit) }}"
|
||||||
|
user_search_base: "{{ provider.user_search_base | default(omit) }}"
|
||||||
|
user_filter: "{{ provider.user_filter | default(omit) }}"
|
||||||
|
admin_filter: "{{ provider.admin_filter | default(omit) }}"
|
||||||
|
username_attribute: "{{ provider.username_attribute | default(omit) }}"
|
||||||
|
email_attribute: "{{ provider.email_attribute | default(omit) }}"
|
||||||
|
firstname_attribute: "{{ provider.firstname_attribute | default(omit) }}"
|
||||||
|
surname_attribute: "{{ provider.surname_attribute | default(omit) }}"
|
||||||
|
sshkey_attribute: "{{ provider.sshkey_attribute | default(omit) }}"
|
||||||
|
sync_users: "{{ provider.sync_users | default(omit) }}"
|
||||||
|
provider: "{{ provider.provider | default(omit) }}"
|
||||||
|
client_id: "{{ provider.client_id | default(omit) }}"
|
||||||
|
client_secret: "{{ provider.client_secret | default(omit) }}"
|
||||||
|
auto_discover_url: "{{ provider.auto_discover_url | default(omit) }}"
|
||||||
|
use_custom_urls: "{{ provider.use_custom_urls | default(omit) }}"
|
||||||
|
custom_tenant_id: "{{ provider.custom_tenant_id | default(omit) }}"
|
||||||
|
custom_auth_url: "{{ provider.custom_auth_url | default(omit) }}"
|
||||||
|
custom_email_url: "{{ provider.custom_email_url | default(omit) }}"
|
||||||
|
custom_profile_url: "{{ provider.custom_profile_url | default(omit) }}"
|
||||||
|
custom_token_url: "{{ provider.custom_token_url | default(omit) }}"
|
||||||
|
state: present
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_facts['env']['PATH'] }}:/usr/local/bin"
|
||||||
|
loop: "{{ gitea_auth_providers }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: provider
|
||||||
|
label: "{{ provider.name }}"
|
||||||
|
no_log: "{{ provider.bind_password is defined or provider.client_secret is defined }}"
|
||||||
|
|
||||||
|
- name: 'install custom files'
|
||||||
|
copy:
|
||||||
|
src: "{{ gitea_custom_files }}/"
|
||||||
|
dest: "{{ gitea_custom_path }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
directory_mode: 0755
|
||||||
|
when: "gitea_custom_files is defined"
|
||||||
|
notify: 'restart gitea'
|
||||||
|
|
||||||
|
# If the unit file changed, reload it now.
|
||||||
|
- meta: flush_handlers
|
||||||
|
|
||||||
|
- name: 'enable and start Gitea'
|
||||||
|
service:
|
||||||
|
name: 'gitea'
|
||||||
|
enabled: true
|
||||||
|
state: "{{ ansible_facts['is_chroot'] | ternary(omit, 'started') }}"
|
||||||
10
templates/app.ini.j2
Normal file
10
templates/app.ini.j2
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{# vim: filetype=ini.jinja2 #}
|
||||||
|
{{ ansible_managed | comment }}
|
||||||
|
|
||||||
|
{% for key, options in _gitea_options.items() %}
|
||||||
|
[{{ key }}]
|
||||||
|
{% for k, v in options.items() if v != omit %}
|
||||||
|
{{ k }} = {{ v }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
45
templates/gitea.openrc.j2
Normal file
45
templates/gitea.openrc.j2
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{# vim: filetype=gentoo-init-d.jinja2 #}
|
||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
name=gitea
|
||||||
|
description="Gitea, a self-hosted Git service"
|
||||||
|
|
||||||
|
: ${GITEA_CONF:=/etc/gitea/app.ini}
|
||||||
|
: ${GITEA_USER:={{ gitea_user }}}
|
||||||
|
: ${GITEA_GROUP:={{ gitea_group }}}
|
||||||
|
: ${GITEA_WORK_DIR:={{ gitea_data_path }}}
|
||||||
|
: ${GITEA_CUSTOM:={{ gitea_custom_path }}}
|
||||||
|
: ${GITEA_LOG_FILE:={{ gitea_log_path }}/http.log}
|
||||||
|
|
||||||
|
supervisor=supervise-daemon
|
||||||
|
command="/usr/local/bin/gitea"
|
||||||
|
command_args="--config '${GITEA_CONF}' web"
|
||||||
|
command_background="true"
|
||||||
|
command_user="${GITEA_USER}:${GITEA_GROUP}"
|
||||||
|
error_log="/var/log/${RC_SVCNAME}/${RC_SVCNAME}.err"
|
||||||
|
pidfile="/run/${RC_SVCNAME}.pid"
|
||||||
|
required_files="${GITEA_CONF}"
|
||||||
|
supervise_daemon_args="--env GITEA_WORK_DIR='${GITEA_WORK_DIR}' \
|
||||||
|
--chdir '${GITEA_WORK_DIR}' \
|
||||||
|
--stdout '${GITEA_LOG_FILE}' --stderr '${GITEA_LOG_FILE}'"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
use logger dns
|
||||||
|
need net
|
||||||
|
{%- if gitea_database_host.startswith('127.') or gitea_database_host.startswith('localhost') or gitea_database_host.startswith('/') %}
|
||||||
|
{% if gitea_database_type == 'postgres' %}
|
||||||
|
postgresql
|
||||||
|
{% elif gitea_database_type == 'mysql' %}
|
||||||
|
{% if _initd_mariadb.stat.exists %}
|
||||||
|
mariadb
|
||||||
|
{% else %}
|
||||||
|
mysql
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
after firewall
|
||||||
|
}
|
||||||
32
templates/gitea.service.j2
Normal file
32
templates/gitea.service.j2
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{# vim: filetype=systemd.jinja2 #}
|
||||||
|
[Unit]
|
||||||
|
Description=Gitea (Git with a cup of tea)
|
||||||
|
After=network.target
|
||||||
|
Requires=network.target
|
||||||
|
{% if gitea_database_host.startswith('127.') or gitea_database_host.startswith('localhost') or gitea_database_host.startswith('/') %}
|
||||||
|
{% if gitea_database_type == 'postgres' %}
|
||||||
|
Requires=postgresql.service
|
||||||
|
{% elif gitea_database_type == 'mysql' %}
|
||||||
|
{% if _mariadb_service.stat.exists %}
|
||||||
|
Requires=mariadb.service
|
||||||
|
{% else %}
|
||||||
|
Requires=mysql.service
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2s
|
||||||
|
|
||||||
|
User={{ gitea_user }}
|
||||||
|
Group={{ gitea_group }}
|
||||||
|
|
||||||
|
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
|
||||||
|
WorkingDirectory={{ gitea_data_path | quote }}
|
||||||
|
RuntimeDirectory=gitea
|
||||||
|
Environment="GITEA_WORK_DIR={{ gitea_data_path }}" "GITEA_CUSTOM={{ gitea_custom_path }}"
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
38
templates/gitea_override.conf.j2
Normal file
38
templates/gitea_override.conf.j2
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{# vim: filetype=systemd.jinja2 #}
|
||||||
|
[Service]
|
||||||
|
# Apply principle of least privilege
|
||||||
|
NoNewPrivileges=true
|
||||||
|
CapabilityBoundingSet=
|
||||||
|
{% if gitea_port | int < 1024 %}
|
||||||
|
# Allow binding to low ports
|
||||||
|
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||||
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||||
|
{% endif %}
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ReadWritePaths={{ [gitea_data_path, gitea_log_path] | map('quote') | join(' ') }}
|
||||||
|
{% if gitea_inaccessible_paths | count %}
|
||||||
|
InaccessiblePaths={{ [gitea_inaccessible_paths] | flatten | unique | map('quote') | join(' ') }}
|
||||||
|
{% endif %}
|
||||||
|
PrivateTmp=true
|
||||||
|
PrivateDevices=true
|
||||||
|
{% if [gitea_extra_groups | default([])] | flatten | count == 0 %}
|
||||||
|
PrivateUsers=true
|
||||||
|
{% endif %}
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
ProtectProc=invisible
|
||||||
|
ProtectClock=true
|
||||||
|
ProtectHostname=true
|
||||||
|
LockPersonality=true
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||||
|
RestrictNamespaces=true
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
SystemCallFilter=@system-service @basic-io @io-event @network-io madvise
|
||||||
|
SystemCallFilter=~@aio @chown @keyring @memlock @privileged @resources @setuid
|
||||||
|
SystemCallArchitectures=native
|
||||||
|
RemoveIPC=true
|
||||||
8
vars/alpine.yml
Normal file
8
vars/alpine.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
gitea_has_pkg: true
|
||||||
|
gitea_pkg_name:
|
||||||
|
- 'gitea'
|
||||||
|
- 'gitea-openrc'
|
||||||
|
gitea_pkg_user: 'gitea'
|
||||||
|
gitea_pkg_group: 'www-data'
|
||||||
|
gitea_gnupg_package: 'gnupg'
|
||||||
3
vars/archlinux.yml
Normal file
3
vars/archlinux.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
gitea_has_pkg: true
|
||||||
|
gitea_gnupg_package: 'gnupg'
|
||||||
9
vars/default.yml
Normal file
9
vars/default.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
gitea_has_pkg: false
|
||||||
|
gitea_pkg_name: 'gitea'
|
||||||
|
gitea_pkg_user: 'git'
|
||||||
|
gitea_pkg_group: "{{ gitea_pkg_user }}"
|
||||||
|
gitea_gnupg_package: 'gnupg2'
|
||||||
|
gitea_dependencies:
|
||||||
|
- 'git'
|
||||||
|
- "{{ gitea_gnupg_package }}"
|
||||||
3
vars/gentoo.yml
Normal file
3
vars/gentoo.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
gitea_has_pkg: true
|
||||||
|
gitea_gnupg_package: 'app-crypt/gnupg'
|
||||||
74
vars/main.yml
Normal file
74
vars/main.yml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
gitea_arch: "{{ 'amd64' if ansible_facts['architecture'] == 'x86_64' else ansible_facts['architecture'] }}"
|
||||||
|
gitea_base_url: 'https://dl.gitea.io/gitea/'
|
||||||
|
gitea_pgp_fingerprint: '7C9E68152594688862D62AF62D9AE806EC1592E2'
|
||||||
|
gitea_default_options:
|
||||||
|
DEFAULT:
|
||||||
|
RUN_USER: "{{ gitea_user }}"
|
||||||
|
RUN_MODE: 'prod'
|
||||||
|
repository:
|
||||||
|
ROOT: "{{ gitea_data_path }}/repos"
|
||||||
|
SCRIPT_TYPE: "{{ _bin_bash.stat.exists | ternary('bash', 'sh') }}"
|
||||||
|
git:
|
||||||
|
HOME_PATH: "{{ _gitea_options['server']['APP_DATA_PATH'] | default(gitea_data_path) ~ '/data/' }}/home"
|
||||||
|
repository.signing:
|
||||||
|
SIGNING_KEY: "{{ gitea_enable_signing | bool | ternary('default', 'none') }}"
|
||||||
|
server:
|
||||||
|
APP_DATA_PATH: "{{ gitea_data_path }}"
|
||||||
|
PROTOCOL: "{{ (gitea_tls_cert is defined) | ternary('https', 'http') }}"
|
||||||
|
DOMAIN: "{{ ansible_facts['fqdn'] }}"
|
||||||
|
HTTP_ADDR: "{{ gitea_bind_address }}"
|
||||||
|
HTTP_PORT: "{{ gitea_port }}"
|
||||||
|
SSH_LISTEN_HOST: "{{ gitea_bind_address }}"
|
||||||
|
OFFLINE_MODE: true
|
||||||
|
CERT_FILE: "{{ gitea_tls_cert | default(omit) }}"
|
||||||
|
KEY_FILE: "{{ gitea_tls_cert_key | default(omit) }}"
|
||||||
|
LFS_START_SERVER: "{{ gitea_enable_lfs }}"
|
||||||
|
LFS_JWT_SECRET: '`{{ _LFS_JWT_SECRET }}`'
|
||||||
|
database:
|
||||||
|
DB_TYPE: "{{ gitea_database_type | mandatory }}"
|
||||||
|
HOST: "{{ gitea_database_host | default(omit) }}"
|
||||||
|
NAME: "{{ (gitea_database_type != 'sqlite3') | ternary(gitea_database_name | default(omit), omit) }}"
|
||||||
|
USER: "{{ gitea_database_user | default(omit) }}"
|
||||||
|
PASSWD: "{{ '`' ~ gitea_database_password ~ '`' if gitea_database_password is defined else omit }}"
|
||||||
|
CHARSET: 'utf8mb4'
|
||||||
|
PATH: "{{ (gitea_database_type == 'sqlite3') | ternary(gitea_database_name | default(omit), omit) }}"
|
||||||
|
LOG_SQL: "{{ gitea_loglevel | lower in ['trace', 'debug'] }}"
|
||||||
|
indexer:
|
||||||
|
REPO_INDEXER_ENABLED: "{{ gitea_enable_indexer | bool }}"
|
||||||
|
security:
|
||||||
|
INSTALL_LOCK: true
|
||||||
|
SECRET_KEY: '`{{ _SECRET_KEY }}`'
|
||||||
|
INTERNAL_TOKEN: '`{{ _INTERNAL_TOKEN }}`'
|
||||||
|
COOKIE_USERNAME: 'gitea_user'
|
||||||
|
COOKIE_REMEMBER_NAME: 'gitea_persistent'
|
||||||
|
PASSWORD_HASH_ALGO: 'argon2'
|
||||||
|
service:
|
||||||
|
ENABLE_NOTIFY_MAIL: "{{ gitea_enable_mailer }}"
|
||||||
|
mailer:
|
||||||
|
ENABLED: "{{ gitea_enable_mailer }}"
|
||||||
|
SMTP_ADDR: "{% if ':' in gitea_mailer_host | default('') %}{{ gitea_mailer_host.split(':')[0] }}{% else %}{{ gitea_mailer_host | default(omit) }}{% endif %}"
|
||||||
|
SMTP_PORT: "{% if ':' in gitea_mailer_host | default('') %}{{ gitea_mailer_host.split(':')[1] }}{% else %}{{ omit }}{% endif %}"
|
||||||
|
FROM: "{{ gitea_mailer_from | default(omit) }}"
|
||||||
|
USER: "{{ gitea_mailer_user | default(omit) }}"
|
||||||
|
PASSWD: "{{ '`' ~ gitea_mailer_password ~ '`' if gitea_mailer_password is defined else omit }}"
|
||||||
|
SEND_AS_PLAIN_TEXT: true
|
||||||
|
PROTOCOL: "{% if gitea_mailer_host is defined %}{{ gitea_mailer_host.startswith('/') | ternary('smtp+unix', 'smtp') }}{% else %}sendmail{% endif %}"
|
||||||
|
session:
|
||||||
|
COOKIE_SECURE: "{{ gitea_tls_cert is defined }}"
|
||||||
|
COOKIE_NAME: 'gitea_session'
|
||||||
|
log:
|
||||||
|
ROOT_PATH: "{{ gitea_log_path }}"
|
||||||
|
# Default logger
|
||||||
|
MODE: 'file'
|
||||||
|
LEVEL: "{{ gitea_loglevel }}"
|
||||||
|
# Router logger
|
||||||
|
ROUTER: 'file'
|
||||||
|
ROUTER_LOG_LEVEL: "{{ gitea_loglevel }}"
|
||||||
|
# Access logger
|
||||||
|
ENABLE_ACCESS_LOG: "{{ gitea_loglevel | lower in ['trace', 'debug'] }}"
|
||||||
|
ACCESS: 'file'
|
||||||
|
oauth2:
|
||||||
|
JWT_SECRET: '`{{ _JWT_SECRET }}`'
|
||||||
|
other:
|
||||||
|
SHOW_FOOTER_VERSION: false
|
||||||
Loading…
Reference in New Issue
Block a user