20 Commits

Author SHA1 Message Date
Tom
bfabc38a46 Merge pull request 'New options in the app.ini template.' (#2) from development into main
Reviewed-on: ghost-automation/ds-gitea#2
2026-02-15 15:37:27 +01:00
818626b236 New options in the app.ini template. 2026-02-15 15:29:33 +01:00
Tom
d3927f6c5d Merge pull request 'Templated registration config.' (#1) from development into main
Reviewed-on: ghost-automation/ds-gitea#1
2026-02-12 07:20:30 +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
Tom
e4ea3a420d Merge pull request 'Added unregistered view.' (#10) from development into main
Reviewed-on: http://gitea.tomsitcafe.com:3000/iron/ds-gitea/pulls/10
2026-02-11 21:43:35 +01:00
14d463a882 Added unregistered view. 2026-02-11 21:41:48 +01:00
DeadSwitch
1816d8a585 Merge pull request 'Readme update and registration admin verification.' (#9) from development into main
Reviewed-on: http://gitea.tomsitcafe.com:3000/iron/ds-gitea/pulls/9
2026-02-11 17:18:47 +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
DeadSwitch
09e8534569 Merge pull request 'Certbot (Let's Encrypt) support.' (#8) from development into main
Reviewed-on: http://gitea.tomsitcafe.com:3000/iron/ds-gitea/pulls/8
2026-02-11 13:20:18 +01:00
6928e8cf54 Readme license and version badges. 2026-02-11 13:17:51 +01:00
dc1b18019a Https to http in the lightweight example. 2026-02-11 13:14:05 +01:00
02426968fb Added an examples folder. 2026-02-11 13:12:25 +01:00
edb227a763 Let's Encrypt support with certbot. 2026-02-11 13:01:55 +01:00
c03f0a0f4f Fixed a minor nginx warning.
And re-indented the template.
2026-02-10 14:43:29 +01:00
DeadSwitch
7b0b2e8194 Merge pull request 'Proxy and SSL support' (#7) from development into main
Reviewed-on: http://gitea.tomsitcafe.com:3000/iron/ds-gitea/pulls/7
2026-02-10 13:52:44 +01:00
2cca3d5403 Fixed the SSH clone issue.
The git user needs shell and a disabled password.
2026-02-10 13:36:42 +01:00
9e68459916 Minor readme update. 2026-02-10 12:31:20 +01:00
e23f9b1901 Added reverse proxy support. 2026-02-10 12:13:24 +01:00
10 changed files with 325 additions and 40 deletions

View File

@@ -1,27 +1,33 @@
#+TITLE: Gitea Server Installer Role #+TITLE: Gitea Server Role
#+AUTHOR: DeadSwitch | The Silent Architect #+AUTHOR: DeadSwitch | The Silent Architect
#+OPTIONS: toc:nil num:nil \n:t #+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.2-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. It uses SQLite as its default database service - with optional PostgreSQL support (=ds-posgresql=).
Use the =ds-ufw= role to configure the firewall. The role can set up a reverse proxy with SSL using Nginx (=ds-nginx=).
Self-signed certificates and Let's Encrypt with =certbot= are supported.
Use the =ds-posgresql= to configure the database. The =ds-ufw= role can configure the firewall.
* Role Workflow The =ds-act_runner= role can configure and register Actions runners.
* Role Behavior
1. Download and install the Gitea binary 1. Download and install the Gitea binary
2. (Optionally) Set up the PostgreSQL user and database 2. (Optionally) Set up the PostgreSQL user and database
3. Set up the user and group for the service 3. (Optionally) Set up an =nginx= reverse proxy with SSL support
4. Create the required directory structure 4. Create a user and group for the service
5. Wait for the secret creation and storage in SOPS - if secrets are not present 5. Create the required directory structure
6. Deploy the Gitea configuration 6. Wait to save the secrets in SOPS (only if secrets are not present)
7. Deploy the Gitea systemd service file (With Postgresql support if the backend is used) 7. Deploy the Gitea =app.ini= configuration
8. Enable and start the service 8. Deploy the Gitea systemd service
9. Enable and start the services
* Defaults * Defaults
@@ -30,21 +36,28 @@ gitea_user: git
gitea_group: git gitea_group: git
gitea_http_port: 3000 gitea_http_port: 3000
gitea_ssh_port: 22 gitea_ssh_port: 22
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 #+end_src
* Requirements * Requirements
- Ansible >= 2.12 - Ansible >= 2.12
- Debian-based OS (Bookworm, Trixie) - Debian 12+ or compatible
- git - git
- sudo - sudo
- ca-certificates - ca-certificates
- (optional) PosgreSQL database - (optional) PosgreSQL database
- (optional) Nginx server
- (optional) certbot for Let's Encrypt
* Variables * Variables
| Variable | Type | Comment | | Variable | Type | Comment |
|-----------------------+--------+----------------------------------------------| |----------------------------------+---------+--------------------------------------------------|
| gitea_user | string | Gitea user | | gitea_user | string | Gitea user |
| gitea_group | string | Gitea group | | gitea_group | string | Gitea group |
| gitea_binary_url | string | Download URL of Gitea | | gitea_binary_url | string | Download URL of Gitea |
@@ -60,6 +73,19 @@ gitea_ssh_port: 22
| gitea_jwt_secret | string | JWT secret | | gitea_jwt_secret | string | JWT secret |
| gitea_database_server | string | DB server - 'postgresql' or empty for sqlite | | gitea_database_server | string | DB server - 'postgresql' or empty for sqlite |
| gitea_db_password | string | PosgreSQL db password (if pgsql is used) | | 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 |
| 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 |
* Handlers * Handlers
@@ -68,9 +94,9 @@ gitea_ssh_port: 22
* Secrets * Secrets
Always store 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 #+begin_src shell
gitea generate secret INTERNAL_TOKEN gitea generate secret INTERNAL_TOKEN
@@ -83,6 +109,8 @@ Then re-run the playbook to finish the installation.
* Example Playbook * Example Playbook
You can find more playbook examples in the =examples= directory.
#+begin_src yaml #+begin_src yaml
- name: Deploy a Gitea server - name: Deploy a Gitea server
hosts: gitea hosts: gitea
@@ -97,12 +125,25 @@ Then re-run the playbook to finish the installation.
gitea_ssh_domain: gitea.tomsitcafe.com gitea_ssh_domain: gitea.tomsitcafe.com
gitea_domain: gitea.tomsitcafe.com gitea_domain: gitea.tomsitcafe.com
gitea_http_port: 3000 gitea_http_port: 3000
gitea_root_url: http://gitea.tomsitcafe.com:3000 gitea_root_url: https://gitea.tomsitcafe.com
# Optional # Optional Postgresql database backend
gitea_database_server: postgresql gitea_database_server: postgresql
# In prod put these secrets in SOPS: # Optional Nginx reverse proxy configuration
gitea_reverse_proxy: nginx
gitea_enable_https: true # Use HTTPS
gitea_self_signed: false # Don't generate self-signed certs
gitea_lets_encrypt: true # Use certbot
gitea_enable_http_redirect: true # Redirect HTTP to HTTPS
# Certbot configuration
gitea_certbot_email: email@domain.tld
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
# In prod put the secrets in SOPS:
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4 gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw
gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU

View File

@@ -3,3 +3,8 @@ gitea_user: git
gitea_group: git gitea_group: git
gitea_http_port: 3000 gitea_http_port: 3000
gitea_ssh_port: 22 gitea_ssh_port: 22
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

@@ -0,0 +1,34 @@
---
- name: Install Gitea
hosts: gitea
become: true
roles:
- role: ds-postgresql
- role: ds-nginx
- role: ds-gitea
vars:
gitea_user: git
gitea_group: git
gitea_database_server: postgresql
gitea_binary_url: https://dl.gitea.com/gitea/1.25.4/gitea-1.25.4-linux-amd64
gitea_checksum_url: https://dl.gitea.com/gitea/1.25.4/gitea-1.25.4-linux-amd64.sha256
gitea_app_name: Tom's IT Cafe Test Gitea Server
gitea_domain: gitea.tomsitcafe.com
gitea_ssh_domain: "{{ gitea_domain }}"
gitea_http_port: 3000
gitea_ssh_port: 22
gitea_root_url: https://{{ gitea_domain }}
gitea_reverse_proxy: nginx
gitea_enable_https: true
gitea_lets_encrypt: true
gitea_enable_http_redirect: true
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
# Secrets to SOPS
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw
gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU
gitea_db_password: Eegh7Aothooph7pa6eu7eitha_zaim0G

View File

@@ -0,0 +1,21 @@
- name: Install Gitea
hosts: gitea
become: true
roles:
- role: ds-gitea
vars:
gitea_user: git
gitea_group: git
gitea_binary_url: https://dl.gitea.com/gitea/1.25.4/gitea-1.25.4-linux-amd64
gitea_checksum_url: https://dl.gitea.com/gitea/1.25.4/gitea-1.25.4-linux-amd64.sha256
gitea_app_name: Tom's IT Cafe Test Gitea Server
gitea_domain: gitea.tomsitcafe.com
gitea_ssh_domain: "{{ gitea_domain }}"
gitea_http_port: 3000
gitea_ssh_port: 22
gitea_root_url: http://{{ gitea_domain }}:{{ gitea_http_port }}
# Secrets to SOPS
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw
gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU

View File

@@ -0,0 +1,31 @@
- name: Install Gitea
hosts: gitea
become: true
roles:
- role: ds-postgresql
- role: ds-nginx
- role: ds-gitea
vars:
gitea_user: git
gitea_group: git
gitea_database_server: postgresql
gitea_binary_url: https://dl.gitea.com/gitea/1.25.4/gitea-1.25.4-linux-amd64
gitea_checksum_url: https://dl.gitea.com/gitea/1.25.4/gitea-1.25.4-linux-amd64.sha256
gitea_app_name: Tom's IT Cafe Test Gitea Server
gitea_domain: gitea.tomsitcafe.com
gitea_ssh_domain: "{{ gitea_domain }}"
gitea_http_port: 3000
gitea_ssh_port: 22
gitea_root_url: https://{{ gitea_domain }}
gitea_reverse_proxy: nginx
gitea_enable_https: true
gitea_self_signed: true
gitea_ssl_cert: /var/lib/gitea/certs/cert.pem
gitea_ssl_key: /var/lib/gitea/certs/key.pem
gitea_enable_http_redirect: true
# Secrets to SOPS
gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4
gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw
gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU
gitea_db_password: Eegh7Aothooph7pa6eu7eitha_zaim0G

29
tasks/lets-encrypt.yml Normal file
View File

@@ -0,0 +1,29 @@
---
- name: Install certbot
ansible.builtin.apt:
name:
- certbot
state: present
- name: Ensure webroot directory exists
ansible.builtin.file:
path: /var/www/html/.well-known/acme-challenge
state: directory
owner: www-data
group: www-data
mode: '0755'
- name: Obtain or renew TLS certificate (non-destructive)
ansible.builtin.command:
cmd: >
certbot certonly
--webroot
-w /var/www/html
-d {{ gitea_domain }}
--agree-tos
--email {{ gitea_certbot_email }}
--non-interactive
--keep-until-expiring
register: certbot_result
changed_when: "'Congratulations' in certbot_result.stdout"
notify: Reload_nginx

View File

@@ -44,6 +44,28 @@
- Reload_postgresql - Reload_postgresql
when: gitea_database_server | default('') == "postgresql" when: gitea_database_server | default('') == "postgresql"
- name: Set up the reverse proxy
block:
- name: Deploy the site configuration
ansible.builtin.template:
src: gitea.j2
dest: /etc/nginx/sites-available/gitea
owner: root
group: root
mode: '0644'
notify: Reload_nginx
- name: Enable the gitea site
ansible.builtin.file:
src: /etc/nginx/sites-available/gitea
dest: /etc/nginx/sites-enabled/gitea
state: link
owner: root
group: root
force: true
notify: Reload_nginx
when: gitea_reverse_proxy | default('') == "nginx"
- name: Create the gitea group - name: Create the gitea group
ansible.builtin.group: ansible.builtin.group:
name: "{{ gitea_group }}" name: "{{ gitea_group }}"
@@ -54,7 +76,8 @@
name: "{{ gitea_user }}" name: "{{ gitea_user }}"
group: "{{ gitea_group }}" group: "{{ gitea_group }}"
home: /home/{{ gitea_user }} home: /home/{{ gitea_user }}
shell: /usr/sbin/nologin shell: /bin/bash
password: '*'
system: true system: true
create_home: true create_home: true
@@ -71,6 +94,16 @@
group: "{{ gitea_group }}" group: "{{ gitea_group }}"
mode: '0750' mode: '0750'
- name: Generate self-signed certificates
ansible.builtin.include_tasks:
file: self-signed-cert.yml
when: gitea_self_signed | default(false)
- name: Configure the Let's Encrypt certificates
ansible.builtin.include_tasks:
file: lets-encrypt.yml
when: gitea_lets_encrypt | default(false)
- name: Pause to generate and save the secrets in SOPS - name: Pause to generate and save the secrets in SOPS
ansible.builtin.pause: ansible.builtin.pause:
prompt: | prompt: |

View File

@@ -0,0 +1,18 @@
---
- name: Create the certs directory
ansible.builtin.file:
path: /var/lib/gitea/certs
owner: "{{ gitea_user }}"
group: "{{ gitea_group }}"
mode: '0750'
state: directory
- name: Generate the self-signed certs for Gitea
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
become_user: "{{ gitea_user }}"
args:
creates: /var/lib/gitea/certs/cert.pem

View File

@@ -50,14 +50,15 @@ ENABLED = false
[service] [service]
REGISTER_EMAIL_CONFIRM = false REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false ENABLE_NOTIFY_MAIL = false
DISABLE_REGISTRATION = false DISABLE_REGISTRATION = {{ gitea_disable_registration }}
ALLOW_ONLY_EXTERNAL_REGISTRATION = false ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = false ENABLE_CAPTCHA = {{ gitea_enable_captcha }}
REQUIRE_SIGNIN_VIEW = false REQUIRE_SIGNIN_VIEW = {{ gitea_require_signin_view }}
DEFAULT_KEEP_EMAIL_PRIVATE = false DEFAULT_KEEP_EMAIL_PRIVATE = {{ gitea_default_keep_email_private }}
DEFAULT_ALLOW_CREATE_ORGANIZATION = true DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING = true DEFAULT_ENABLE_TIMETRACKING = true
NO_REPLY_ADDRESS = noreply.localhost NO_REPLY_ADDRESS = noreply.localhost
REGISTER_MANUAL_CONFIRM = {{ gitea_register_manual_confirm }}
[openid] [openid]
ENABLE_OPENID_SIGNIN = false ENABLE_OPENID_SIGNIN = false

72
templates/gitea.j2 Normal file
View File

@@ -0,0 +1,72 @@
# {{ ansible_managed }}
{% if gitea_enable_https | default(false) %}
server {
listen 443 ssl;
http2 on;
server_name {{ gitea_domain }};
ssl_certificate {{ gitea_ssl_cert }};
ssl_certificate_key {{ gitea_ssl_key }};
{% if gitea_lets_encrypt | default(false) %}
ssl_trusted_certificate {{ gitea_ssl_trusted_certificate }};
{% endif %}
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 50M;
location / {
client_max_body_size 512M;
proxy_pass http://localhost:{{ gitea_http_port }};
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
{% if gitea_enable_http_redirect | default(true) %}
server {
listen 80;
server_name {{ gitea_domain }};
{% if gitea_lets_encrypt | default(false) %}
# Allow Let's Encrypt to verify certificates
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
allow all;
}
# Redirect everything else to HTTPS
location / {
return 301 https://$host$request_uri;
}
{% else %}
return 301 https://$host$request_uri;
{% endif %}
}
{% endif %}
{% else %}
# HTTP-only configuration
server {
listen 80;
server_name {{ gitea_domain }};
client_max_body_size 50M;
location / {
client_max_body_size 512M;
proxy_pass http://localhost:{{ gitea_http_port }};
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
{% endif %}