13 Commits

Author SHA1 Message Date
c77128583a Bugfix: The git service user's $HOME changed to the workdir.
All checks were successful
Test the role / test-the-role (push) Successful in 8s
This bug prevented the gitea.service to start properly.
The new git home is the 'gitea_work_path' - default to /var/lib/gitea.
2026-02-26 10:46:33 +01:00
53cb178ee8 Updated the readme for the 3.1.0 release.
All checks were successful
Test the role / test-the-role (push) Successful in 7s
2026-02-25 10:19:57 +01:00
d0245e00b7 Configurable workdirs and paths.
All checks were successful
Test the role / test-the-role (push) Successful in 8s
2026-02-23 19:04:02 +01:00
39ca068451 Linting in CI.
All checks were successful
Test the role / test-the-role (push) Successful in 8s
2026-02-18 17:59:46 +01:00
0153639c38 Preparing v3.0.3. 2026-02-18 17:16:30 +01:00
c81f75b055 Readme update. 2026-02-18 16:58:19 +01:00
02dd1f773e Linter validation. 2026-02-18 16:54:14 +01:00
818626b236 New options in the app.ini template. 2026-02-15 15:29:33 +01:00
1120daab40 Templated registration config.
Self-registration can be turned off.
Admin verification can be set.
Guest users' read-only view can be configured.
2026-02-12 07:16:52 +01:00
14d463a882 Added unregistered view. 2026-02-11 21:41:48 +01:00
a22b78d585 Registered users must be activated by admin. 2026-02-11 17:07:40 +01:00
aafa72a464 Removed the db password from the light example. 2026-02-11 17:07:23 +01:00
ae3af7ea83 Major readme update. 2026-02-11 15:17:09 +01:00
10 changed files with 135 additions and 95 deletions

10
.gitea/workflows/test.yml Normal file
View File

@@ -0,0 +1,10 @@
name: Test the role
on:
- push
jobs:
test-the-role:
runs-on: iron-runner
steps:
- uses: actions/checkout@v6
- run: ansible-lint --profile production .

View File

@@ -1,34 +1,30 @@
#+TITLE: Gitea Server Installer Role
#+TITLE: Gitea Server Role
#+AUTHOR: DeadSwitch | The Silent Architect
#+OPTIONS: toc:nil num:nil \n:t
[[https://opensource.org/licenses/MIT][https://img.shields.io/badge/license-MIT-blue.svg]] [[https://img.shields.io/badge/version-3.0.0-green.svg]]
[[https://opensource.org/licenses/MIT][https://img.shields.io/badge/license-MIT-blue.svg]] [[https://img.shields.io/badge/version-3.1.0-green.svg]]
* ds-gitea
* ds_gitea
This role installs and configures a [[https://docs.gitea.com/][Gitea]] server.
This role can install and configures a [[https://docs.gitea.com/][Gitea]] server.
It uses SQLite as its default database service - with optional PostgreSQL support.
The role can set up a reverse proxy with SSL using Nginx.
Self-signed certificates and Let's Encrypt with =certbot= are supported.
- Use the =ds-ufw= role to configure the firewall.
- Use the =ds-posgresql= role to configure the database.
- Use the =ds-nginx= role to install the proxy server.
- Use the =ds-act_runner= role to configure and register Actions runners.
- Defaults to SQLite backend with optional PostgreSQL support (Install it with =ds_posgresql=).
- It can set up a reverse proxy with SSL using Nginx (Install it with =ds_nginx=).
- The role supports self-signed certificates and /Let's Encrypt/ with =certbot=.
- The =ds_ufw= role can configure the host firewall.
- The =ds_act_runner= role can configure and register /Gitea Actions/ runners.
* Role Behavior
1. Download and install the Gitea binary
2. (Optionally) Set up the PostgreSQL user and database
3. Set up the user and group for the service
4. Create the required directory structure
5. Wait for the secret creation and storage in SOPS - if secrets are not present
6. Deploy the Gitea configuration
7. Deploy the Gitea systemd service file
8. (Optionally) Set up the reverse proxy with optional SSL
9. Enable and start the service
3. (Optionally) Set up an =nginx= reverse proxy with SSL support
4. Create a user and group for the service
5. Create the required directory structure
6. Wait for the operator to save the secrets in SOPS or Ansible Vault (only if secrets are not present)
7. Deploy the Gitea =app.ini= configuration
8. Deploy the Gitea systemd service
9. Enable and start the services
* Defaults
@@ -37,8 +33,16 @@ gitea_user: git
gitea_group: git
gitea_http_port: 3000
gitea_ssh_port: 22
gitea_database_server: ''
gitea_reverse_proxy: ''
gitea_work_path: /var/lib/gitea
gitea_app_data_path: /var/lib/gitea/data
gitea_repo_root: /var/lib/gitea/data/gitea-repositories
gitea_lfs_path: /var/lib/gitea/data/lfs
gitea_log_path: /var/lib/gitea/log
gitea_require_signin_view: true
gitea_disable_registration: true
gitea_register_manual_confirm: false
gitea_enable_captcha: false
gitea_default_keep_email_private: true
#+end_src
* Requirements
@@ -50,57 +54,66 @@ gitea_reverse_proxy: ''
- ca-certificates
- (optional) PosgreSQL database
- (optional) Nginx server
- (optional) certbot for Let's Encrypt
* Variables
| Variable | Type | Comment |
|----------------------------+---------+----------------------------------------------|
| gitea_user | string | Gitea user |
| gitea_group | string | Gitea group |
| gitea_binary_url | string | Download URL of Gitea |
| gitea_checksum_url | string | Checksum URL of the binary |
| gitea_app_name | string | Gitea server title |
| gitea_ssh_domain | string | SSH domain |
| gitea_domain | string | Domain to reach Gitea |
| gitea_http_port | int | HTTP port |
| gitea_ssh_port | int | SSH port |
| gitea_root_url | string | Protocol + FQDN + port |
| gitea_lfs_jwt_secret | string | LFS storage secret |
| gitea_internal_token | string | Internal token |
| gitea_jwt_secret | string | JWT secret |
| gitea_database_server | string | DB server - 'postgresql' or empty for sqlite |
| gitea_db_password | string | PosgreSQL db password (if pgsql is used) |
| gitea_reverse_proxy | string | Reverse proxy to use or not set for no proxy |
| gitea_enable_https | boolean | Configure HTTPS in the proxy |
| gitea_ssl_cert | string | SSL certificate |
| gitea_ssl_key | string | SSL key |
| gitea_enable_http_redirect | boolean | Redirect HTTP to HTTPS |
| gitea_self_signed | boolean | Generate a self-signed cert and key |
| gitea_lets_encrypt | boolean | Use certbot to configure the SSL |
| gitea_certbot_email | string | Email to register the certificates |
* Handlers
- =Reload_systemd=: It runs a =daemon-reload=
- =Restart_gitea=: It restarts the Gitea service
| Variable | Type | Comment |
|----------------------------------+---------+---------------------------------------------------------|
| gitea_user | string | Gitea user |
| gitea_group | string | Gitea group |
| gitea_binary_url | string | Download URL of Gitea |
| gitea_checksum_url | string | Checksum URL of the binary |
| gitea_app_name | string | Gitea server title |
| gitea_ssh_domain | string | SSH domain |
| gitea_domain | string | Domain to reach Gitea |
| gitea_http_port | int | HTTP port |
| gitea_ssh_port | int | SSH port |
| gitea_work_path | string | Workdir |
| gitea_app_data_path | string | Application data path |
| gitea_repo_root | string | Repo root path |
| gitea_lfs_path | string | LFS path |
| gitea_log_path | string | Log path |
| gitea_root_url | string | Protocol + FQDN + port |
| gitea_lfs_jwt_secret | string | LFS storage secret |
| gitea_internal_token | string | Internal token |
| gitea_jwt_secret | string | JWT secret |
| gitea_database_server | string | DB server - 'postgresql' or empty for sqlite |
| gitea_db_password | string | PosgreSQL db password (if pgsql is used) |
| gitea_reverse_proxy | string | 'nginx' to set up a reverse proxy or empty for no proxy |
| gitea_enable_https | boolean | Configure HTTPS in the proxy |
| gitea_ssl_cert | string | Path to the SSL certificate |
| gitea_ssl_key | string | Path to the SSL key |
| gitea_ssl_trusted_certificate | string | Path to the SSL certificate chain |
| gitea_enable_http_redirect | boolean | Redirect HTTP traffic to HTTPS |
| gitea_self_signed | boolean | Generate a self-signed certificate and key |
| gitea_lets_encrypt | boolean | Use certbot to configure HTTPS |
| gitea_certbot_email | string | Email to register the certificates |
| gitea_require_signin_view | boolean | If false, public repos are visible without login |
| gitea_disable_registration | boolean | Turn off the user registration feature |
| gitea_register_manual_confirm | boolean | Registration requires admin verification |
| gitea_enable_captcha | boolean | Enable captcha for registration |
| gitea_default_keep_email_private | boolean | Default email policy: private |
* Secrets
Always save the production secrets in SOPS, or in Ansible Vault.
Always save the production secrets in SOPS or in Ansible Vault.
Generate the secrets manually when the playbook stops:
You can generate the secrets manually when the playbook stops:
#+begin_src shell
gitea generate secret INTERNAL_TOKEN
gitea generate secret JWT_SECRET
#+end_src
Use the =JWT_SECRET= command to generate the =gitea_lfs_jwt_secret= as well. It's an alias.
Use the =JWT_SECRET= option to generate the =gitea_lfs_jwt_secret= as well.
Then re-run the playbook to finish the installation.
* Example Playbook
You can find more playbook examples in the =examples= directory.
#+begin_src yaml
- name: Deploy a Gitea server
hosts: gitea
@@ -140,7 +153,7 @@ Then re-run the playbook to finish the installation.
gitea_db_password: Eegh7Aothooph7pa6eu7eitha_zaim0G
roles:
- role: ds-gitea
- role: ds_gitea
#+end_src
* License

View File

@@ -3,3 +3,13 @@ gitea_user: git
gitea_group: git
gitea_http_port: 3000
gitea_ssh_port: 22
gitea_work_path: /var/lib/gitea
gitea_app_data_path: /var/lib/gitea/data
gitea_repo_root: /var/lib/gitea/data/gitea-repositories
gitea_lfs_path: /var/lib/gitea/data/lfs
gitea_log_path: /var/lib/gitea/log
gitea_require_signin_view: true
gitea_disable_registration: true
gitea_register_manual_confirm: false
gitea_enable_captcha: false
gitea_default_keep_email_private: true

View File

@@ -4,9 +4,9 @@
become: true
roles:
- role: ds-postgresql
- role: ds-nginx
- role: ds-gitea
- role: ds_postgresql
- role: ds_nginx
- role: ds_gitea
vars:
gitea_user: git
gitea_group: git
@@ -26,9 +26,9 @@
gitea_certbot_email: tom@tomsitcafe.com
gitea_ssl_cert: /etc/letsencrypt/live/{{ gitea_domain }}/fullchain.pem
gitea_ssl_key: /etc/letsencrypt/live/{{ gitea_domain }}/privkey.pem
gitea_ssl_trusted_certificate: /etc/letsencrypt/live/{{ gitea_domain }}/chain.pem
gitea_ssl_trusted_certificate: /etc/letsencrypt/live/{{ gitea_domain }}/chain.pem
# Secrets to SOPS
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw
gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU
gitea_db_password: Eegh7Aothooph7pa6eu7eitha_zaim0G

View File

@@ -3,7 +3,7 @@
become: true
roles:
- role: ds-gitea
- role: ds_gitea
vars:
gitea_user: git
gitea_group: git
@@ -16,7 +16,6 @@
gitea_ssh_port: 22
gitea_root_url: http://{{ gitea_domain }}:{{ gitea_http_port }}
# Secrets to SOPS
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw
gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU
gitea_db_password: Eegh7Aothooph7pa6eu7eitha_zaim0G

View File

@@ -3,9 +3,9 @@
become: true
roles:
- role: ds-postgresql
- role: ds-nginx
- role: ds-gitea
- role: ds_postgresql
- role: ds_nginx
- role: ds_gitea
vars:
gitea_user: git
gitea_group: git
@@ -25,7 +25,7 @@
gitea_ssl_key: /var/lib/gitea/certs/key.pem
gitea_enable_http_redirect: true
# Secrets to SOPS
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw
gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU
gitea_db_password: Eegh7Aothooph7pa6eu7eitha_zaim0G

View File

@@ -9,6 +9,7 @@
state: present
- name: Set up the PostgreSQL database
when: gitea_database_server | default('') == "postgresql"
block:
- name: Ensure PostgreSQL Python client is installed
ansible.builtin.apt:
@@ -21,6 +22,7 @@
name: gitea
password: "{{ gitea_db_password }}"
role_attr_flags: "NOSUPERUSER,NOCREATEDB,NOCREATEROLE"
become: true
become_user: postgres
- name: Create the gitea database
@@ -31,6 +33,7 @@
encoding: UTF8
lc_collate: en_US.UTF-8
lc_ctype: en_US.UTF-8
become: true
become_user: postgres
- name: Ensure pg_hba.conf has local access for gitea
@@ -39,12 +42,12 @@
regexp: '^local\s+giteadb\s+gitea\s+'
line: 'local giteadb gitea scram-sha-256'
state: present
backup: yes
backup: true
notify:
- Reload_postgresql
when: gitea_database_server | default('') == "postgresql"
- name: Set up the reverse proxy
when: gitea_reverse_proxy | default('') == "nginx"
block:
- name: Deploy the site configuration
ansible.builtin.template:
@@ -64,7 +67,6 @@
group: root
force: true
notify: Reload_nginx
when: gitea_reverse_proxy | default('') == "nginx"
- name: Create the gitea group
ansible.builtin.group:
@@ -74,18 +76,22 @@
- name: Create the gitea user
ansible.builtin.user:
name: "{{ gitea_user }}"
comment: "Gitea Service User"
group: "{{ gitea_group }}"
home: /home/{{ gitea_user }}
home: "{{ gitea_work_path }}"
shell: /bin/bash
password: '*'
system: true
create_home: true
- name: Download the Gitea binary
ansible.builtin.get_url:
url: "{{ gitea_binary_url }}"
dest: /usr/local/bin/gitea
checksum: "sha256:{{ gitea_checksum_url }}"
owner: "{{ gitea_user }}"
group: "{{ gitea_group }}"
mode: '0750'
- name: Set the permissions of the Gitea binary
ansible.builtin.file:
@@ -103,7 +109,7 @@
ansible.builtin.include_tasks:
file: lets-encrypt.yml
when: gitea_lets_encrypt | default(false)
- name: Pause to generate and save the secrets in SOPS
ansible.builtin.pause:
prompt: |
@@ -125,7 +131,7 @@
- name: Create the data dir base
ansible.builtin.file:
path: /var/lib/gitea
path: "{{ gitea_work_path }}"
owner: "{{ gitea_user }}"
group: "{{ gitea_group }}"
mode: '0750'
@@ -139,9 +145,9 @@
mode: '0750'
state: directory
loop:
- /var/lib/gitea/custom
- /var/lib/gitea/data
- /var/lib/gitea/log
- "{{ gitea_work_path }}/custom"
- "{{ gitea_app_data_path }}"
- "{{ gitea_log_path }}"
- name: Create the config dir
ansible.builtin.file:
@@ -170,7 +176,7 @@
mode: '0640'
notify:
- Restart_gitea
- name: Start and enable Gitea
ansible.builtin.systemd_service:
name: gitea.service

View File

@@ -1,7 +1,7 @@
---
- name: Create the certs directory
ansible.builtin.file:
path: /var/lib/gitea/certs
path: "{{ gitea_work_path }}/certs"
owner: "{{ gitea_user }}"
group: "{{ gitea_group }}"
mode: '0750'
@@ -11,8 +11,9 @@
ansible.builtin.command: >
gitea cert
--host {{ gitea_domain }},{{ gitea_ssh_domain }}
--out /var/lib/gitea/certs/cert.pem
--keyout /var/lib/gitea/certs/key.pem
--out {{ gitea_work_path }}/certs/cert.pem
--keyout {{ gitea_work_path }}/certs/key.pem
become: true
become_user: "{{ gitea_user }}"
args:
creates: /var/lib/gitea/certs/cert.pem
creates: "{{ gitea_work_path }}/certs/cert.pem"

View File

@@ -2,7 +2,7 @@
APP_NAME = {{ gitea_app_name }}
RUN_USER = {{ gitea_user }}
WORK_PATH = /var/lib/gitea
WORK_PATH = {{ gitea_work_path }}
RUN_MODE = prod
{% if gitea_database_server | default('') == "postgresql" %}
@@ -22,19 +22,19 @@ USER = {{ gitea_user }}
PASSWD =
SCHEMA =
SSL_MODE = disable
PATH = /var/lib/gitea/data/gitea.db
PATH = {{ gitea_app_data_path }}/gitea.db
LOG_SQL = false
{% endif %}
[repository]
ROOT = /var/lib/gitea/data/gitea-repositories
ROOT = {{ gitea_repo_root }}
[server]
SSH_DOMAIN = {{ gitea_ssh_domain }}
DOMAIN = {{ gitea_domain }}
HTTP_PORT = {{ gitea_http_port }}
ROOT_URL = {{ gitea_root_url }}
APP_DATA_PATH = /var/lib/gitea/data
APP_DATA_PATH = {{ gitea_app_data_path }}
DISABLE_SSH = false
SSH_PORT = {{ gitea_ssh_port }}
LFS_START_SERVER = true
@@ -42,7 +42,7 @@ LFS_JWT_SECRET = {{ gitea_lfs_jwt_secret }}
OFFLINE_MODE = true
[lfs]
PATH = /var/lib/gitea/data/lfs
PATH = {{ gitea_lfs_path }}
[mailer]
ENABLED = false
@@ -50,14 +50,15 @@ ENABLED = false
[service]
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
DISABLE_REGISTRATION = false
DISABLE_REGISTRATION = {{ gitea_disable_registration }}
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = false
REQUIRE_SIGNIN_VIEW = false
DEFAULT_KEEP_EMAIL_PRIVATE = false
ENABLE_CAPTCHA = {{ gitea_enable_captcha }}
REQUIRE_SIGNIN_VIEW = {{ gitea_require_signin_view }}
DEFAULT_KEEP_EMAIL_PRIVATE = {{ gitea_default_keep_email_private }}
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING = true
NO_REPLY_ADDRESS = noreply.localhost
REGISTER_MANUAL_CONFIRM = {{ gitea_register_manual_confirm }}
[openid]
ENABLE_OPENID_SIGNIN = false
@@ -72,7 +73,7 @@ PROVIDER = file
[log]
MODE = console
LEVEL = info
ROOT_PATH = /var/lib/gitea/log
ROOT_PATH = {{ gitea_log_path }}
[repository.pull-request]
DEFAULT_MERGE_STYLE = merge

View File

@@ -13,10 +13,10 @@ RestartSec=2s
Type=simple
User={{ gitea_user }}
Group={{ gitea_group }}
WorkingDirectory=/var/lib/gitea/
WorkingDirectory={{ gitea_work_path }}
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER={{ gitea_user }} HOME=/home/{{ gitea_user }} GITEA_WORK_DIR=/var/lib/gitea
Environment=USER={{ gitea_user }} HOME={{ gitea_work_path }} GITEA_WORK_DIR={{ gitea_work_path }}
[Install]
WantedBy=multi-user.target