.
This commit is contained in:
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') }}"
|
||||
Reference in New Issue
Block a user