diff options
| author | Miguel Dalberto Pedro <miguel.pedro@precisioninno.com> | 2026-10-29 16:42:44 -0300 |
|---|---|---|
| committer | Miguel Dalberto Pedro <miguel.pedro@precisioninno.com> | 2026-10-29 16:42:44 -0300 |
| commit | eab4f5746a69783e4e3a3c05808ab58b5d2f494d (patch) | |
| tree | ff6e149dccbd5ccc999d9e4f648bed823433ffab | |
| parent | 4b7379914a1865f07b2c54252234cc90158fc253 (diff) | |
| download | my-infra-eab4f5746a69783e4e3a3c05808ab58b5d2f494d.tar.gz my-infra-eab4f5746a69783e4e3a3c05808ab58b5d2f494d.zip | |
- Enable cgit role (cgit_enabled: true) for git.miguelpedro.xyz.br
- Provision dedicated 'git' user/group (/srv/git, git-shell, authorized_keys)
- Add custom git-shell commands ('init' and 'list') for remote bare repo creation
- Configure /etc/cgitrc with HTTP clone support, Pygments syntax highlighting, and README rendering
- Add Nginx virtual host with automatic TLS upgrade once Let's Encrypt cert is present
- Update DISCOVERY_REPORT.md, COMMAND_LOG.md, README.md, and AGENT_INSTRUCTIONS.md per Self-Updating Protocol
| -rw-r--r-- | AGENT_INSTRUCTIONS.md | 11 | ||||
| -rw-r--r-- | COMMAND_LOG.md | 37 | ||||
| -rw-r--r-- | DISCOVERY_REPORT.md | 26 | ||||
| -rw-r--r-- | README.md | 41 | ||||
| -rw-r--r-- | group_vars/all/vars.yml | 9 | ||||
| -rw-r--r-- | roles/cgit/handlers/main.yml | 5 | ||||
| -rw-r--r-- | roles/cgit/tasks/main.yml | 124 | ||||
| -rw-r--r-- | roles/cgit/templates/cgitrc.j2 | 11 | ||||
| -rw-r--r-- | roles/cgit/templates/site-cgit.conf.j2 | 60 |
9 files changed, 305 insertions, 19 deletions
diff --git a/AGENT_INSTRUCTIONS.md b/AGENT_INSTRUCTIONS.md index 45410d3..b6c6e4c 100644 --- a/AGENT_INSTRUCTIONS.md +++ b/AGENT_INSTRUCTIONS.md @@ -51,3 +51,14 @@ Before ending your session or creating a final commit, you **MUST** update the r - Created roles for `common`, `certbot`, `valkey`, `searxng`, `nginx`, and scaffolded `cgit` (`cgit_enabled: false`) for upcoming deployment. - Cleaned up unused Nginx stub symlink (`/etc/nginx/sites-enabled/miguelpedro.xyz.br` which pointed to `example.com`) via `nginx_remove_unused_sites`. - **Verification:** Verified playbook against live VPS with `ansible-playbook site.yml --check --diff`. + + +### [2026-10-29] Deploy cgit + fcgiwrap & Dedicated `git` SSH Server +- **Agent Action:** + - Enabled `cgit_enabled: true` in `group_vars/all/vars.yml`. + - Expanded `roles/cgit` to install `cgit`, `fcgiwrap`, `python3-pygments`, `python3-markdown`, and `python3-docutils`. + - Provisioned dedicated `git` system user/group (`999:989`, home `/srv/git`, shell `/usr/bin/git-shell`) with SSH `authorized_keys` and custom `git-shell-commands` (`init` and `list`). + - Added `www-data` to the `git` group and configured `/var/www/.gitconfig` (`safe.directory = *`) so `cgit`/`fcgiwrap` can read bare repositories in `/srv/git`. + - Configured `/etc/cgitrc` with HTTP clone support (`enable-http-clone=1`), syntax highlighting, and README rendering. + - Deployed `/etc/nginx/sites-available/cgit.conf` (and enabled symlink) for `git.miguelpedro.xyz.br`, blocking `git-receive-pack` over HTTP (`403`) and auto-upgrading to TLS once the Certbot certificate for `git.miguelpedro.xyz.br` is present. +- **Verification:** Applied `ansible-playbook site.yml --tags "cgit" --diff`, verified `cgit v1.2.3` HTTP response, CSS delivery, and `ssh git@miguelpedro.xyz.br list`, and confirmed full idempotency (`ok=42 changed=0`). diff --git a/COMMAND_LOG.md b/COMMAND_LOG.md index e386d19..c530013 100644 --- a/COMMAND_LOG.md +++ b/COMMAND_LOG.md @@ -593,3 +593,40 @@ vps : ok=28 changed=3 unreachable=0 failed=0 skipped=6 rescued=0 ignored=0 ``` - **Verified 1:1 match (`ok`):** `common` packages, `certbot` timer & certs, `valkey` service, `searxng` user/group/dirs/git/settings.yml/limiter.toml/uwsgi.ini, `nginx.conf`, `default.apps-available/searxng.conf`, and `sites-available/searxng.conf`. - **Expected cleanups flagged (`changed`):** Removing unused `/etc/nginx/sites-enabled/miguelpedro.xyz.br` stub symlink (`example.com`) and trailing blank lines in `/etc/nginx/sites-available/default`. + + +--- + +## 10. cgit & fcgiwrap Deployment and Verification (2026-10-29) +**Pre-flight Check:** +```bash +.venv/bin/ansible-playbook site.yml --check --diff +``` +**Output:** `ok=27 changed=0 failed=0` + +**Apply `cgit` Role:** +```bash +.venv/bin/ansible-playbook site.yml --tags "cgit" --diff +``` +**Output:** `ok=18 changed=16 failed=0` (Installed `cgit`, `fcgiwrap`, `python3-docutils`, `python3-markdown`, `python3-pygments`; created `git` user/group `999:989`; added `www-data` to `git` group; configured `/srv/git` with `02750` and `git-shell-commands`; deployed `/etc/cgitrc` and `/etc/nginx/sites-available/cgit.conf`; reloaded `nginx` and restarted `fcgiwrap`). + +**Health & SSH Verification:** +```bash +ssh root@miguelpedro.xyz.br ' +curl -s -i -H "Host: git.miguelpedro.xyz.br" http://127.0.0.1/ | head -n 35 +curl -s -I -H "Host: git.miguelpedro.xyz.br" http://127.0.0.1/cgit-css/cgit.css +id git; id www-data +' +ssh -o BatchMode=yes git@miguelpedro.xyz.br list +``` +**Output:** +- `http://127.0.0.1/` (`Host: git.miguelpedro.xyz.br`) returned `cgit v1.2.3` HTML (`Miguel Pedro Git Repositories`). +- `/cgit-css/cgit.css` returned `HTTP/1.1 200 OK` (`text/css`, `15112` bytes). +- `uid=999(git) gid=989(git)`, `uid=33(www-data) gid=33(www-data) groups=33(www-data),989(git)`. +- `ssh git@miguelpedro.xyz.br list` connected cleanly via `git-shell` with exit code `0`. + +**Post-Apply Idempotency Check:** +```bash +.venv/bin/ansible-playbook site.yml --check --diff +``` +**Output:** `ok=42 changed=0 unreachable=0 failed=0 skipped=0` diff --git a/DISCOVERY_REPORT.md b/DISCOVERY_REPORT.md index ab45750..dea8c08 100644 --- a/DISCOVERY_REPORT.md +++ b/DISCOVERY_REPORT.md @@ -16,6 +16,11 @@ Internet (Ports 80/443) [ Nginx Reverse Proxy & Web Server ] (/etc/nginx) ├── miguelpedro.xyz.br / www.miguelpedro.xyz.br ──► Static files (/var/www/html) ├── _ (default_server :80) ───────────────────────► Static files + /searxng sub-path + ├── git.miguelpedro.xyz.br (:80 / :443) + │ │ + │ ▼ (Unix Socket: /run/fcgiwrap.socket) + │ [ fcgiwrap Daemon ] ──► /usr/lib/cgit/cgit.cgi (/etc/cgitrc) + │ Scans bare Git repos in /srv/git (user/group `git` 999:989) └── searx.miguelpedro.xyz.br (HTTPS :443) │ ▼ (Unix Socket: /usr/local/searxng/run/socket) @@ -46,13 +51,27 @@ Internet (Ports 80/443) - Security headers: `X-Frame-Options "SAMEORIGIN"`, `X-Content-Type-Options "nosniff"`, `Referrer-Policy "no-referrer"`, `Strict-Transport-Security "max-age=31536000; includeSubDomains"`. - Proxies `location /` via `uwsgi_pass unix:///usr/local/searxng/run/socket;` with `HTTP_HOST`, `HTTP_CONNECTION`, `HTTP_X_SCHEME`, `HTTP_X_REAL_IP`, and `HTTP_X_FORWARDED_FOR`. - Port 80 redirect block for `searx.miguelpedro.xyz.br` (301 to HTTPS). - 3. **`miguelpedro.xyz.br` (`-> /etc/nginx/sites-available/miguelpedro.xyz.br`)**: - - Port 80 stub with `server_name example.com www.example.com;` pointing to `/var/www/miguelpedro.xyz.br/html` (currently an empty directory, while the active `miguelpedro.xyz.br` site is served from `sites-available/default`). + 3. **`cgit.conf` (`-> /etc/nginx/sites-available/cgit.conf`)**: + - Serves `git.miguelpedro.xyz.br`, mapping static assets `/cgit-css/*` to `/usr/share/cgit/` and passing CGI requests to `unix:/run/fcgiwrap.socket` (`/usr/lib/cgit/cgit.cgi`). Blocks `git-receive-pack` over HTTP (`403`) so pushes remain strictly over SSH. Automatically upgrades to HTTPS once `/etc/letsencrypt/live/git.miguelpedro.xyz.br/fullchain.pem` is provisioned. + 4. **`miguelpedro.xyz.br` (disabled stub in `/etc/nginx/sites-available/miguelpedro.xyz.br`)**: + - Symlink removed from `/etc/nginx/sites-enabled/` via Ansible (`nginx_remove_unused_sites`). - **Default App Includes (`/etc/nginx/default.d/`):** - `/etc/nginx/default.d/searxng.conf -> /etc/nginx/default.apps-available/searxng.conf` (created by SearXNG's official installation script, exposing `location /searxng` on the default server block). --- +## 2b. cgit & Git Server (`git.miguelpedro.xyz.br`) + +- **Packages:** `cgit`, `fcgiwrap`, `git`, `python3-pygments`, `python3-markdown`, `python3-docutils` +- **Services:** `fcgiwrap.socket` and `fcgiwrap.service` (active, enabled; socket `/run/fcgiwrap.socket`). +- **System User & Group:** `git` (`UID=999`, `GID=989`, home `/srv/git`, shell `/usr/bin/git-shell`). `www-data` is a member of the `git` group (`989`) to allow `cgit`/`fcgiwrap` read access, with `/var/www/.gitconfig` configuring `safe.directory = *`. +- **Repositories Root:** `/srv/git` (`02750` `git:git`) + - `/srv/git/.ssh/authorized_keys` (`0600` `git:git`): Contains authorized SSH public keys. + - `/srv/git/git-shell-commands/`: Custom `git-shell` helper commands (`init`, `list`, `no-interactive-login`) allowing remote creation of bare repositories via `ssh git@miguelpedro.xyz.br init <repo>.git "<description>"`. +- **Configuration:** `/etc/cgitrc` (enables `enable-http-clone=1`, syntax highlighting via Pygments, README rendering, and `scan-path=/srv/git`). + +--- + ## 3. SearXNG, uWSGI & Valkey SearXNG was installed using the official SearXNG installation script (`utils/searxng.sh`), running natively via `uwsgi` and backed by `valkey-server`. @@ -121,7 +140,8 @@ SearXNG was installed using the official SearXNG installation script (`utils/sea | Component | Critical Path on VPS | Purpose | | :--- | :--- | :--- | | **Nginx Core** | `/etc/nginx/nginx.conf` | Global Nginx settings (`server_tokens off`, TLS 1.2/1.3) | -| **Nginx VHosts** | `/etc/nginx/sites-available/default`<br>`/etc/nginx/sites-available/searxng.conf`<br>`/etc/nginx/sites-available/miguelpedro.xyz.br` | Main domain vhost, SearXNG reverse proxy vhost, and stub config | +| **Nginx VHosts** | `/etc/nginx/sites-available/default`<br>`/etc/nginx/sites-available/searxng.conf`<br>`/etc/nginx/sites-available/cgit.conf` | Main domain vhost, SearXNG reverse proxy vhost, and cgit vhost | +| **cgit & Git Repos** | `/etc/cgitrc`<br>`/srv/git/`<br>`/srv/git/git-shell-commands/`<br>`/run/fcgiwrap.socket` | cgit configuration, bare Git repositories (`git:git`), `git-shell` helpers, and FastCGI socket | | **Nginx App Snippet** | `/etc/nginx/default.apps-available/searxng.conf` | `/searxng` sub-path snippet symlinked in `/etc/nginx/default.d/` | | **Web Root** | `/var/www/html/`<br>`/var/www/miguelpedro.xyz.br/html/` | Static web roots | | **SearXNG Config** | `/etc/searxng/settings.yml`<br>`/etc/searxng/limiter.toml` | SearXNG instance settings, secret key, Valkey URL, and bot limiter | @@ -8,11 +8,11 @@ This repository manages the configuration and state of the `miguelpedro.xyz.br` | Service | Domain / Endpoint | Role | Description | | :--- | :--- | :--- | :--- | -| **Nginx** | `miguelpedro.xyz.br`<br>`searx.miguelpedro.xyz.br` | [`roles/nginx`](file:///home/mpedro/Repos/my-infra/roles/nginx/tasks/main.yml) | Reverse proxy, TLS termination, and static web server | +| **Nginx** | `miguelpedro.xyz.br`<br>`searx.miguelpedro.xyz.br`<br>`git.miguelpedro.xyz.br` | [`roles/nginx`](file:///home/mpedro/Repos/my-infra/roles/nginx/tasks/main.yml) | Reverse proxy, TLS termination, and static web server | | **Certbot** | `/etc/letsencrypt/` | [`roles/certbot`](file:///home/mpedro/Repos/my-infra/roles/certbot/tasks/main.yml) | Automated Let's Encrypt ECDSA certificate management (`certbot.timer`) | | **SearXNG** | `https://searx.miguelpedro.xyz.br/` | [`roles/searxng`](file:///home/mpedro/Repos/my-infra/roles/searxng/tasks/main.yml) | Privacy-respecting metasearch engine served via `uwsgi` Unix socket | | **Valkey** | `127.0.0.1:6379` | [`roles/valkey`](file:///home/mpedro/Repos/my-infra/roles/valkey/tasks/main.yml) | Local key-value store backing SearXNG's rate limiter and bot detection | -| **cgit** *(Prepared)* | `git.miguelpedro.xyz.br` | [`roles/cgit`](file:///home/mpedro/Repos/my-infra/roles/cgit/tasks/main.yml) | Ready-to-enable role (`cgit_enabled: false`) for self-hosted Git web UI via `fcgiwrap` | +| **cgit** | `https://git.miguelpedro.xyz.br/` | [`roles/cgit`](file:///home/mpedro/Repos/my-infra/roles/cgit/tasks/main.yml) | Self-hosted Git web UI (`cgit` + `fcgiwrap`), HTTP clone support, and `git@` SSH hosting (`/srv/git`) | --- @@ -84,13 +84,34 @@ Sensitive values (such as `vault_searxng_secret_key`) are encrypted in [`group_v --- -## 4. Deploying `cgit` (Upcoming) +## 4. Using `cgit` & Managing Git Repositories -The `cgit` role ([`roles/cgit`](file:///home/mpedro/Repos/my-infra/roles/cgit/tasks/main.yml)) is already scaffolded. When ready to deploy: -1. Ensure DNS for `cgit_domain` (default `git.miguelpedro.xyz.br`) points to the VPS. -2. In [`group_vars/all/vars.yml`](file:///home/mpedro/Repos/my-infra/group_vars/all/vars.yml), set: - ```yaml - cgit_enabled: true +`cgit` is active (`cgit_enabled: true`) and serves repositories from `/srv/git` under the dedicated `git` user (`git-shell`). + +### Creating a New Repository via SSH +A custom `git-shell` helper command (`init`) is installed so you can create bare repositories remotely without logging into root: +```bash +ssh git@miguelpedro.xyz.br init my-project.git "My project description" +``` + +### Listing Existing Repositories via SSH +```bash +ssh git@miguelpedro.xyz.br list +``` + +### Pushing to a Repository +```bash +git remote add origin git@miguelpedro.xyz.br:my-project.git +git push -u origin master +``` + +### Enabling HTTPS for `git.miguelpedro.xyz.br` +Once your DNS `A` record for `git.miguelpedro.xyz.br` points to `189.126.106.41`: +1. Request the Let's Encrypt certificate on the VPS: + ```bash + ssh root@miguelpedro.xyz.br "certbot certonly --nginx -d git.miguelpedro.xyz.br" + ``` +2. Re-run the `cgit` role—[`roles/cgit/templates/site-cgit.conf.j2`](file:///home/mpedro/Repos/my-infra/roles/cgit/templates/site-cgit.conf.j2) automatically detects `/etc/letsencrypt/live/git.miguelpedro.xyz.br/fullchain.pem` and switches the Nginx virtual host to HTTPS with HTTP-to-HTTPS redirect: + ```bash + .venv/bin/ansible-playbook site.yml --tags "cgit" --diff ``` -3. Run `.venv/bin/ansible-playbook site.yml --tags "cgit" --diff`. -4. Provision TLS via Certbot (`certbot --nginx -d git.miguelpedro.xyz.br`) and update [`roles/cgit/templates/site-cgit.conf.j2`](file:///home/mpedro/Repos/my-infra/roles/cgit/templates/site-cgit.conf.j2) to include the SSL directives. diff --git a/group_vars/all/vars.yml b/group_vars/all/vars.yml index 8ecb430..db792fd 100644 --- a/group_vars/all/vars.yml +++ b/group_vars/all/vars.yml @@ -37,8 +37,13 @@ searxng_base_url: "https://{{ searxng_domain }}/" searxng_valkey_url: "valkey://localhost:6379/0" searxng_secret_key: "{{ vault_searxng_secret_key }}" -# Future cgit deployment toggle & defaults -cgit_enabled: false +# cgit & Git server configuration +cgit_enabled: true +cgit_user: git +cgit_group: git cgit_repos_path: /srv/git cgit_title: "Miguel Pedro Git Repositories" cgit_description: "Self-hosted Git repositories powered by cgit" +cgit_enable_http_clone: true +cgit_ssh_authorized_keys: + - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDcBQznFkp2YuQg6zxJ9g/9n3E/byi+z+N3JWRpQu17C migueldalberto.acc@gmail.com" diff --git a/roles/cgit/handlers/main.yml b/roles/cgit/handlers/main.yml new file mode 100644 index 0000000..e4af55c --- /dev/null +++ b/roles/cgit/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart fcgiwrap + ansible.builtin.systemd: + name: fcgiwrap.service + state: restarted diff --git a/roles/cgit/tasks/main.yml b/roles/cgit/tasks/main.yml index 44f9459..f454d93 100644 --- a/roles/cgit/tasks/main.yml +++ b/roles/cgit/tasks/main.yml @@ -4,17 +4,125 @@ name: - cgit - fcgiwrap - - python3-pygments + - git + - python3-docutils - python3-markdown + - python3-pygments + state: present + +- name: Ensure dedicated git system group exists + ansible.builtin.group: + name: "{{ cgit_group }}" + system: true + state: present + +- name: Ensure dedicated git system user exists + ansible.builtin.user: + name: "{{ cgit_user }}" + group: "{{ cgit_group }}" + home: "{{ cgit_repos_path }}" + shell: /usr/bin/git-shell + comment: "Git version control user" + system: true + create_home: true state: present -- name: Ensure Git repositories root directory exists +- name: Add www-data to git group so Nginx/fcgiwrap can read repositories + ansible.builtin.user: + name: www-data + groups: "{{ cgit_group }}" + append: true + notify: Restart fcgiwrap + +- name: Ensure Git repositories root directory permissions (setgid for group inheritance) ansible.builtin.file: path: "{{ cgit_repos_path }}" state: directory + owner: "{{ cgit_user }}" + group: "{{ cgit_group }}" + mode: "02750" + +- name: Configure git user safe.directory for cgit (www-data) + ansible.builtin.copy: + dest: /var/www/.gitconfig owner: www-data group: www-data + mode: "0644" + content: | + [safe] + directory = * + +- name: Ensure git-shell-commands directory exists (disables interactive shell login and provides helpers) + ansible.builtin.file: + path: "{{ cgit_repos_path }}/git-shell-commands" + state: directory + owner: root + group: "{{ cgit_group }}" + mode: "0755" + +- name: Deploy git-shell helper commands (no-interactive-login, init, list) + ansible.builtin.copy: + dest: "{{ cgit_repos_path }}/git-shell-commands/{{ item.name }}" + owner: root + group: "{{ cgit_group }}" mode: "0755" + content: "{{ item.content }}" + loop: + - name: no-interactive-login + content: | + #!/bin/sh + printf '%s\n' "Hi! You've successfully authenticated as '{{ cgit_user }}', but interactive shell access is disabled." + printf '%s\n' "Tip: Run 'ssh {{ cgit_user }}@{{ primary_domain }} init <repo>.git [description]' to create a new repository." + exit 128 + - name: list + content: | + #!/bin/sh + find "{{ cgit_repos_path }}" -maxdepth 2 -name "*.git" -type d -printf "%P\n" | sort + - name: init + content: | + #!/bin/sh + set -e + REPO="$1" + DESC="$2" + if [ -z "$REPO" ]; then + echo "Usage: ssh {{ cgit_user }}@{{ primary_domain }} init <repo-name>.git [description]" + exit 1 + fi + case "$REPO" in + *.git) ;; + *) REPO="${REPO}.git" ;; + esac + TARGET="{{ cgit_repos_path }}/${REPO}" + if [ -d "$TARGET" ]; then + echo "Error: Repository ${REPO} already exists." + exit 1 + fi + git init --bare --shared=group "$TARGET" + if [ -n "$DESC" ]; then + echo "$DESC" > "$TARGET/description" + else + echo "${REPO%.git}" > "$TARGET/description" + fi + echo "Initialized bare repository at {{ cgit_user }}@{{ primary_domain }}:${REPO}" + +- name: Ensure .ssh directory exists for git user + ansible.builtin.file: + path: "{{ cgit_repos_path }}/.ssh" + state: directory + owner: "{{ cgit_user }}" + group: "{{ cgit_group }}" + mode: "0700" + +- name: Configure authorized SSH keys for git user + ansible.builtin.copy: + dest: "{{ cgit_repos_path }}/.ssh/authorized_keys" + owner: "{{ cgit_user }}" + group: "{{ cgit_group }}" + mode: "0600" + content: | + {% for key in cgit_ssh_authorized_keys %} + {{ key }} + {% endfor %} - name: Deploy /etc/cgitrc configuration ansible.builtin.template: @@ -24,11 +132,19 @@ group: root mode: "0644" -- name: Ensure fcgiwrap socket/service is enabled and running +- name: Ensure fcgiwrap socket and service are enabled and running ansible.builtin.systemd: - name: fcgiwrap.socket + name: "{{ item }}" enabled: true state: started + loop: + - fcgiwrap.socket + - fcgiwrap.service + +- name: Check if TLS certificate exists for {{ cgit_domain }} + ansible.builtin.stat: + path: "/etc/letsencrypt/live/{{ cgit_domain }}/fullchain.pem" + register: cgit_tls_cert - name: Deploy Nginx virtual host for cgit ansible.builtin.template: diff --git a/roles/cgit/templates/cgitrc.j2 b/roles/cgit/templates/cgitrc.j2 index 0cae2ab..6e9cbd0 100644 --- a/roles/cgit/templates/cgitrc.j2 +++ b/roles/cgit/templates/cgitrc.j2 @@ -7,11 +7,21 @@ root-title={{ cgit_title }} root-desc={{ cgit_description }} virtual-root=/ +{% if cgit_enable_http_clone | default(true) %} +enable-http-clone=1 +clone-url=https://{{ cgit_domain }}/$CGIT_REPO_URL git@{{ primary_domain }}:$CGIT_REPO_URL +{% else %} +enable-http-clone=0 +clone-url=git@{{ primary_domain }}:$CGIT_REPO_URL +{% endif %} + enable-index-links=1 enable-index-owner=0 enable-commit-graph=1 enable-log-filecount=1 enable-log-linecount=1 +enable-git-config=1 +remove-suffix=1 snapshots=tar.gz zip about-filter=/usr/lib/cgit/filters/about-formatting.sh @@ -23,4 +33,5 @@ readme=:README.rst readme=:README.txt readme=:README +# Scan path must be placed after global repository defaults scan-path={{ cgit_repos_path }} diff --git a/roles/cgit/templates/site-cgit.conf.j2 b/roles/cgit/templates/site-cgit.conf.j2 index 557c364..36753d3 100644 --- a/roles/cgit/templates/site-cgit.conf.j2 +++ b/roles/cgit/templates/site-cgit.conf.j2 @@ -1,3 +1,55 @@ +{% if cgit_tls_cert.stat.exists | default(false) %} +server { + server_name {{ cgit_domain }}; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + root /usr/share/cgit; + try_files $uri @cgit; + + # Serve static cgit assets directly + location ~* ^/cgit-css/(.*)$ { + alias /usr/share/cgit/$1; + expires 30d; + } + + # Block git-Receive-pack over HTTP (pushing is strictly via SSH as git@) + location ~ ^/.*/git-receive-pack$ { + return 403; + } + + location @cgit { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi; + fastcgi_param PATH_INFO $uri; + fastcgi_param QUERY_STRING $args; + fastcgi_param HTTP_HOST $server_name; + fastcgi_pass unix:/run/fcgiwrap.socket; + } + + listen 443 ssl; # managed by Certbot / Ansible + listen [::]:443 ssl; # managed by Certbot / Ansible + ssl_certificate /etc/letsencrypt/live/{{ cgit_domain }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ cgit_domain }}/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; +} + +server { + if ($host = {{ cgit_domain }}) { + return 301 https://$host$request_uri; + } + + listen 80; + listen [::]:80; + server_name {{ cgit_domain }}; + return 404; +} +{% else %} server { listen 80; listen [::]:80; @@ -6,8 +58,15 @@ server { root /usr/share/cgit; try_files $uri @cgit; + # Serve static cgit assets directly location ~* ^/cgit-css/(.*)$ { alias /usr/share/cgit/$1; + expires 30d; + } + + # Block git-receive-pack over HTTP (pushing is strictly via SSH as git@) + location ~ ^/.*/git-receive-pack$ { + return 403; } location @cgit { @@ -19,3 +78,4 @@ server { fastcgi_pass unix:/run/fcgiwrap.socket; } } +{% endif %} |
