From e23f9b19011bf629714f1ffccc48cfc152c4e068 Mon Sep 17 00:00:00 2001 From: DeadSwitch Date: Tue, 10 Feb 2026 12:13:24 +0100 Subject: [PATCH] Added reverse proxy support. --- README.org | 62 +++++++++++++++++++++++++------------- tasks/main.yml | 27 +++++++++++++++++ tasks/self-signed-cert.yml | 18 +++++++++++ templates/gitea.j2 | 55 +++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 tasks/self-signed-cert.yml create mode 100644 templates/gitea.j2 diff --git a/README.org b/README.org index 1501d46..b56a54f 100644 --- a/README.org +++ b/README.org @@ -8,9 +8,11 @@ This role installs and configures a [[https://docs.gitea.com/][Gitea]] server. It uses SQLite as its default database service - with optional PostgreSQL support. -Use the =ds-ufw= role to configure the firewall. +The role can set up a reverse proxy with SSL. -Use the =ds-posgresql= to configure the database. +- 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. * Role Workflow @@ -21,7 +23,8 @@ Use the =ds-posgresql= to configure the database. 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 (With Postgresql support if the backend is used) -8. Enable and start the service +8. Set up the reverse proxy with optional SSL +9. Enable and start the service * Defaults @@ -30,6 +33,8 @@ gitea_user: git gitea_group: git gitea_http_port: 3000 gitea_ssh_port: 22 +gitea_database_server: '' +gitea_reverse_proxy: '' #+end_src * Requirements @@ -40,26 +45,33 @@ gitea_ssh_port: 22 - sudo - ca-certificates - (optional) PosgreSQL database +- (optional) Nginx server * 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) | +| 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 | * Handlers @@ -99,9 +111,17 @@ Then re-run the playbook to finish the installation. gitea_http_port: 3000 gitea_root_url: http://gitea.tomsitcafe.com:3000 - # Optional + # Optional Postgresql database backend gitea_database_server: postgresql + # Optional Nginx reverse proxy configuration + 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 + # In prod put these secrets in SOPS: gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4 gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw diff --git a/tasks/main.yml b/tasks/main.yml index d39b54c..7011614 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -44,6 +44,28 @@ - Reload_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 ansible.builtin.group: name: "{{ gitea_group }}" @@ -71,6 +93,11 @@ group: "{{ gitea_group }}" mode: '0750' +- name: Generate self-signed certificates + ansible.builtin.include_tasks: + file: self-signed-cert.yml + when: gitea_self_signed | default(false) + - name: Pause to generate and save the secrets in SOPS ansible.builtin.pause: prompt: | diff --git a/tasks/self-signed-cert.yml b/tasks/self-signed-cert.yml new file mode 100644 index 0000000..4fe22c2 --- /dev/null +++ b/tasks/self-signed-cert.yml @@ -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 diff --git a/templates/gitea.j2 b/templates/gitea.j2 new file mode 100644 index 0000000..d586233 --- /dev/null +++ b/templates/gitea.j2 @@ -0,0 +1,55 @@ +# {{ ansible_managed }} + +{% if gitea_enable_https | default(false) %} +server { + listen 443 ssl http2; + server_name {{ gitea_domain }}; + + ssl_certificate {{ gitea_ssl_cert }}; + ssl_certificate_key {{ gitea_ssl_key }}; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 50M; + + location / { + proxy_pass http://127.0.0.1:{{ gitea_http_port }}; + 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; + + proxy_read_timeout 90; + proxy_connect_timeout 90; + } +} + +{% if gitea_enable_http_redirect | default(true) %} +server { + listen 80; + server_name {{ gitea_domain }}; + return 301 https://$host$request_uri; +} +{% endif %} + +{% else %} +# HTTP-only configuration +server { + listen 80; + server_name {{ gitea_domain }}; + + client_max_body_size 50M; + + location / { + proxy_pass http://127.0.0.1:{{ gitea_http_port }}; + 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; + + proxy_read_timeout 90; + proxy_connect_timeout 90; + } +} +{% endif %}