Cut the comment bloat from the Podman playbooks
Comment blocks now stay within three lines and explain only the non-obvious. Long histories, include examples, and commented-out code are gone. No task, key, or value changed; the only data change is comment text inside the generated unit files.
This commit is contained in:
1 parent
2aab1aec1e
commit
476a6d7cd0
85 files changed
+372
-2433
No files matched your search
@@ -1,6 +1,3 @@
|
||||
#################################################
|
||||
# DO Community Playbooks: Docker
|
||||
#################################################
|
||||
---
|
||||
- hosts: all
|
||||
become: true
|
||||
@@ -49,15 +46,3 @@
|
||||
- /var/lib/gitea:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
||||
# - name: Sets Nginx conf file for gitea
|
||||
# template:
|
||||
# src: "files/nginx.conf.j2"
|
||||
# dest: "/etc/nginx/sites-available/{{ http_conf }}"
|
||||
|
||||
# - name: Enables new site
|
||||
# file:
|
||||
# src: "/etc/nginx/sites-available/{{ http_conf }}"
|
||||
# dest: "/etc/nginx/sites-enabled/{{ http_conf }}"
|
||||
# state: link
|
||||
# notify: Reload Nginx
|
||||
+2
-42
@@ -1,33 +1,5 @@
|
||||
---
|
||||
# Gitea as a rootless Podman Quadlet unit on emily, behind the shared Caddy
|
||||
# unit (caddy/playbook.yml), with git-over-SSH still arriving on the host's own
|
||||
# port 22 so that no client has to change its remote.
|
||||
#
|
||||
# Connects as the container user and runs everything as that user: the Quadlet
|
||||
# units belong to it, so the connection's PAM session is what makes
|
||||
# `systemctl --user` work without any environment juggling.
|
||||
#
|
||||
# gather_facts is required: podman_user and the home directory come from the
|
||||
# user_id / user_dir facts.
|
||||
#
|
||||
# The rootless-Podman prerequisites (installing podman, enabling lingering, the
|
||||
# low-port sysctl, creating the Quadlet directory) are deliberately NOT applied
|
||||
# here. They are the shared task file at caddy/roles/podman/tasks/main.yaml, and
|
||||
# a host that has already run caddy/playbook.yml has them:
|
||||
#
|
||||
# - name: Rootless Podman prerequisites
|
||||
# ansible.builtin.include_tasks: "{{ playbook_dir }}/../caddy/roles/podman/tasks/main.yaml"
|
||||
#
|
||||
# The variables this play needs are duplicated at the top of vars/default.yml, so
|
||||
# it stands on its own. (Applying the commented include above would also need
|
||||
# podman_unprivileged_port_start, which lives in caddy/vars/default.yml.)
|
||||
#
|
||||
# Unlike bitwarden/ and tandoor/ there is no postgres role here: this Gitea runs
|
||||
# on SQLite, which monoco's live app.ini confirms (`DB_TYPE = sqlite3`,
|
||||
# `PATH = /data/gitea/gitea.db`). The unused Docker-era Postgres variant that
|
||||
# used to sit beside this file was removed for the same reason.
|
||||
#
|
||||
# Run with: ansible-playbook -u tanshu gitea/playbook.yml
|
||||
# Requires caddy to have run first. Gitea uses SQLite, not Postgres.
|
||||
- name: Deploy Gitea as a rootless Podman Quadlet
|
||||
hosts: emily
|
||||
gather_facts: true
|
||||
@@ -35,23 +7,11 @@
|
||||
- vars/default.yml
|
||||
|
||||
pre_tasks:
|
||||
# This must happen before the app unit is started, not after: the generated
|
||||
# unit references {{ network_name }}.network, and Quadlet fails *unit
|
||||
# generation* (so `systemctl --user start` reports "unit not found") when a
|
||||
# referenced .network file does not exist yet. The same include writes the
|
||||
# Caddy-side drop-in that attaches Caddy to this network.
|
||||
#
|
||||
# network_name is a play var, so the include can see it directly.
|
||||
# Quadlet needs the network unit before it generates the app unit.
|
||||
- name: Register Gitea's network with Caddy
|
||||
ansible.builtin.include_tasks: "{{ playbook_dir }}/../caddy/roles/register/tasks/main.yaml"
|
||||
|
||||
roles:
|
||||
# The host half of git-over-SSH: the `git` login user, the passthrough shim,
|
||||
# the authorized_keys hook, the sshd drop-in and the one-command sudoers
|
||||
# rule. Root-only steps elevate individually — see the role for why.
|
||||
- ssh
|
||||
# The app: the data directory tree the image's own root phase would leave
|
||||
# subuid-owned, the Quadlet unit, start + verify.
|
||||
- gitea
|
||||
# Appends this site's block to the shared Caddyfile and reloads Caddy.
|
||||
- caddy
|
||||
@@ -1,27 +1,14 @@
|
||||
---
|
||||
# Caddy is its own playbook (caddy/playbook.yml) and a rootless Quadlet unit
|
||||
# there. These handlers run as the connection user, so `systemctl --user` and
|
||||
# `podman exec` work without any XDG_RUNTIME_DIR juggling.
|
||||
|
||||
# Notified by this role when the Caddyfile changes. A reload keeps existing
|
||||
# connections; a restart would briefly drop every hosted site.
|
||||
#
|
||||
# Note the config path: /etc/caddy/Caddyfile is the mount inside the container,
|
||||
# not {{ caddyfile_path }}, which is the host side of it.
|
||||
# A reload keeps existing connections. A restart would briefly drop every hosted site.
|
||||
# The config path is inside the container, not caddyfile_path on the host.
|
||||
- name: Reload Caddy configuration
|
||||
ansible.builtin.command: >-
|
||||
podman exec {{ caddy_name }} caddy reload --config /etc/caddy/Caddyfile
|
||||
changed_when: true
|
||||
listen: "Reload Caddy"
|
||||
|
||||
# Notified by caddy/roles/register when this service's network unit, or the
|
||||
# drop-in that attaches Caddy to it, is written. Quadlet has no live equivalent
|
||||
# of `docker network connect`, so the container has to be recreated — a brief
|
||||
# restart of every hosted site, not just this one. See caddy/readme.md,
|
||||
# "Trade-off worth knowing".
|
||||
#
|
||||
# Defined after the reload above so that when both are notified the cheap config
|
||||
# reload happens first.
|
||||
# Quadlet has no live equivalent of network connect, so Caddy is recreated and every hosted site restarts.
|
||||
# Defined after the reload so the cheap reload runs first.
|
||||
- name: Restart Caddy
|
||||
ansible.builtin.systemd_service:
|
||||
name: "{{ caddy_name }}.service"
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
---
|
||||
# Append this site's block to the shared Caddyfile.
|
||||
#
|
||||
# The Caddyfile is a bind mount into the Caddy container, so Caddy sees the
|
||||
# change as soon as the file is written; the handler only asks Caddy to re-read
|
||||
# it. That is a reload, not a restart, so the other hosted sites are untouched.
|
||||
#
|
||||
# blockinfile is idempotent on its own via the marker, so there is no need to
|
||||
# slurp the file and compare first — which also matters because slurp *fails*
|
||||
# when the Caddyfile does not exist yet, on a host where the Caddy playbook has
|
||||
# not run.
|
||||
|
||||
- name: "Add the {{ host }} site block to the Caddyfile"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ caddyfile_path }}"
|
||||
|
||||
@@ -1,33 +1,5 @@
|
||||
---
|
||||
# Gitea as a rootless Podman Quadlet unit.
|
||||
#
|
||||
# Everything here runs as {{ podman_user }} — the connection user. No become, no
|
||||
# XDG_RUNTIME_DIR: the SSH connection gave us a real PAM session, so systemd's
|
||||
# user manager is reachable through the standard environment.
|
||||
|
||||
# The data tree is created here rather than left to the image, and that is not
|
||||
# housekeeping. With keep-id:uid={{ gitea_uid }} the container process runs as
|
||||
# `git`, so /usr/bin/entrypoint is the *only* part of the image's start-up that
|
||||
# root can do — and it needs root for /etc/passwd, /etc/s6 and this tree.
|
||||
#
|
||||
# Container root is a subuid on the host, but inside its user namespace it holds
|
||||
# the usual capabilities, so `mkdir`, `chmod` and `chown` all succeed; what it
|
||||
# creates is simply left owned by that subuid. The image chowns the directories it
|
||||
# knows about back to `git` — `chown -R ${USER}:git /data/gitea` and `/data/git`
|
||||
# in /etc/s6/gitea/setup, which is where app.ini comes from — so those work either
|
||||
# way. The things it does *not* chown are what this task is for, and they are the
|
||||
# ones that would otherwise be subuid-owned and invisible to the app and to a
|
||||
# plain tar backup:
|
||||
#
|
||||
# gitea/ app.ini, gitea.db, sessions, avatars, indexers
|
||||
# gitea/conf where the entrypoint would generate app.ini
|
||||
# gitea/log Gitea's file log
|
||||
# git/ repositories, LFS, and the git account's HOME
|
||||
# git/.ssh authorized_keys — written by Gitea, read by the host's sshd
|
||||
# ssh/ only ever a *mount point* — see below
|
||||
#
|
||||
# The sshd *inside* the image is the exception; it cannot use this tree at all.
|
||||
# See {{ container_sshd_hostkeys }} below.
|
||||
# Create the tree as podman_user: anything left to the image stays subuid-owned and misses a plain tar backup.
|
||||
- name: Ensure the Gitea data directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ host_directory }}"
|
||||
@@ -48,27 +20,12 @@
|
||||
- { path: gitea/conf, mode: '0755' }
|
||||
- { path: gitea/log, mode: '0755' }
|
||||
- { path: git, mode: '0755' }
|
||||
# 0700 because that is what the image's own setup script chmods it to
|
||||
# (`chmod 700 /data/git/.ssh` in /etc/s6/gitea/setup, which runs as root
|
||||
# before `su-exec git`). Set here so the mode never depends on that script
|
||||
# having run.
|
||||
# The image's setup chmods this to 0700; setting it here does not depend on that script.
|
||||
- { path: git/.ssh, mode: '0700' }
|
||||
# The in-image sshd's host keys are mounted over /data/ssh from
|
||||
# {{ container_sshd_hostkeys }}, so this directory is never written to — it
|
||||
# has to *exist*, because it is the mount point. If it does not, Podman
|
||||
# creates it during container set-up, inside the container's user namespace,
|
||||
# and it lands here owned by the subuid rather than by {{ podman_user }}:
|
||||
#
|
||||
# drwxr-xr-t 2 165536 165536 4096 ssh
|
||||
#
|
||||
# which the check at the end of this role then (correctly) fails on. Creating
|
||||
# it first is what keeps the data tree wholly {{ podman_user }}'s.
|
||||
# This is a mount point, so it must exist; letting Podman create it leaves it subuid-owned and fails the owner check.
|
||||
- { path: ssh, mode: '0755' }
|
||||
|
||||
# The image's setup creates this file if it is missing, as root — and it is the
|
||||
# one file under /data the setup never chowns back to `git`, so on a fresh host it
|
||||
# would be left subuid-owned. Writing it here, as {{ podman_user }} and 0600,
|
||||
# both avoids that and states the value the image's own environment carries.
|
||||
# The image would create this as root and never chown it back, leaving it subuid-owned.
|
||||
- name: Write the container-side .ssh/environment file
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ host_directory }}/git/.ssh/environment"
|
||||
@@ -78,16 +35,7 @@
|
||||
group: "{{ podman_user }}"
|
||||
mode: '0600'
|
||||
|
||||
# The image always starts an sshd of its own inside the container, and that sshd
|
||||
# wants host keys. This deployment does not use it — git-over-SSH arrives on the
|
||||
# host's sshd on port 22 — but it has to have somewhere to write, and the process
|
||||
# that runs it maps to a subuid that cannot touch the data directory. Keeping it
|
||||
# out here means no subuid-owned file ever lands in {{ host_directory }}, so a
|
||||
# plain tar/rsync of the data tree stays complete and error-free, and the check
|
||||
# at the end of this role stays meaningful.
|
||||
#
|
||||
# 0777 is deliberate and bounded: /home/{{ podman_user }} is 0750, so no other
|
||||
# host user can reach this path at all. The mode only matters inside the userns.
|
||||
# The in-image sshd runs as a subuid that cannot touch the data directory, and 0777 is safe because the home directory is 0750.
|
||||
- name: Ensure the scratch host key directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_sshd_hostkeys }}"
|
||||
@@ -107,16 +55,7 @@
|
||||
- Reload systemd user units
|
||||
- Restart Gitea
|
||||
|
||||
# Quadlet honours [Install] WantedBy= when it generates the unit, so
|
||||
# `systemctl --user enable` is neither needed nor possible on a generated unit.
|
||||
#
|
||||
# All three steps are in one block because they fail the same way and want the
|
||||
# same evidence. `systemctl start` reports success as soon as it has handed the
|
||||
# unit to systemd, so a container that dies a second later — a `User=0` missing,
|
||||
# an unwritable /data, a subuid that cannot run the image's start-up — surfaces
|
||||
# only as `activating` from `is-active`, or as a health check that never passes,
|
||||
# with the reason in the journal and nowhere else. Restart=always makes that a
|
||||
# crash loop rather than an error.
|
||||
# Quadlet honours [Install] WantedBy=, so the generated unit is never enabled.
|
||||
- name: Start and verify Gitea
|
||||
block:
|
||||
- name: Start Gitea
|
||||
@@ -126,9 +65,7 @@
|
||||
state: started
|
||||
daemon_reload: true
|
||||
|
||||
# Retried rather than checked once: podman reports `activating` for the
|
||||
# interval between systemd starting the container and its readiness
|
||||
# notification.
|
||||
# Retried because podman reports `activating` between start and readiness.
|
||||
- name: Verify Gitea is running
|
||||
ansible.builtin.command: "systemctl --user is-active {{ unit_name }}"
|
||||
register: gitea_active
|
||||
@@ -137,9 +74,7 @@
|
||||
delay: 5
|
||||
changed_when: false
|
||||
|
||||
# `is-active` says the container is running; it does not say the app can
|
||||
# serve. The image ships no HEALTHCHECK, so the unit defines one (HealthCmd=,
|
||||
# see the template) and this runs exactly that command once, synchronously.
|
||||
# The image ships no HEALTHCHECK, so the unit defines one and this runs it synchronously.
|
||||
- name: Wait for Gitea to pass its health check
|
||||
ansible.builtin.command: "podman healthcheck run {{ container_name }}"
|
||||
register: gitea_health
|
||||
@@ -148,10 +83,7 @@
|
||||
delay: 5
|
||||
changed_when: false
|
||||
rescue:
|
||||
# systemd reports "control process exited with error code" and nothing else,
|
||||
# which is useless for the usual failures. The journal is where the image's
|
||||
# own start-up output is — that is where a s6 or entrypoint permission
|
||||
# failure shows up.
|
||||
# systemd only reports "control process exited with error code", so read the journal for the real reason.
|
||||
- name: Collect Gitea diagnostics
|
||||
ansible.builtin.command: "{{ item }}"
|
||||
loop:
|
||||
@@ -170,13 +102,7 @@
|
||||
ansible.builtin.fail:
|
||||
msg: "Gitea did not start — see the diagnostics above."
|
||||
|
||||
# A wrong keep-id is the one failure here that does not look like one: Gitea
|
||||
# still serves, but from files it owns as an unmapped subuid on the host — files
|
||||
# that then disappear from a tar backup and cannot be deleted without
|
||||
# `podman unshare`. Check the whole tree, not a sample.
|
||||
#
|
||||
# Deliberately not `failed_when: false`: if `find` cannot read something in the
|
||||
# data directory, the tree is not provably clean, and that is the finding.
|
||||
# A wrong keep-id still serves, but writes subuid-owned files a tar backup misses, so check the whole tree and let find fail.
|
||||
- name: List anything in the data tree not owned by {{ podman_user }}
|
||||
ansible.builtin.command: >-
|
||||
find {{ host_directory }} ! -user {{ podman_user }}
|
||||
@@ -198,9 +124,7 @@
|
||||
path: "{{ host_directory }}/gitea/gitea.db"
|
||||
register: gitea_db
|
||||
|
||||
# Not a failure: a fresh instance legitimately has no database yet. But on a
|
||||
# migration it means the copy in readme.md has not run, and the instance that is
|
||||
# now serving is an empty installer rather than this repository's Gitea.
|
||||
# Not a failure on a fresh instance, but a migration whose copy never ran will serve an empty installer.
|
||||
- name: Report a data directory with no database in it
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
|
||||
@@ -1,44 +1,11 @@
|
||||
---
|
||||
# The host half of Gitea's git-over-SSH support.
|
||||
#
|
||||
# Port 22 belongs to the host's sshd and stays that way: clients keep using
|
||||
# git@git.tanshu.com:user/repo.git, and no remote URL changes. Four host-side
|
||||
# pieces make that work:
|
||||
#
|
||||
# 1. a `{{ git_user }}` login user with no interactive access — every key
|
||||
# Gitea accepts carries a forced command, so sshd runs the shim and
|
||||
# nothing else;
|
||||
# 2. {{ shim_path }}, the shim those forced commands invoke;
|
||||
# 3. {{ podman_exec_wrapper }} plus a one-command sudoers rule — how the shim,
|
||||
# running as `{{ git_user }}`, reaches a container owned by
|
||||
# {{ podman_user }};
|
||||
# 4. the sshd and sudoers drop-ins that tie the above together.
|
||||
#
|
||||
# What differs from the Docker-era role is the second hop. It used to be an ssh
|
||||
# into an sshd running *inside* the container; under keep-id that sshd runs as a
|
||||
# subuid and cannot read the authorized_keys Gitea writes as {{ podman_user }},
|
||||
# so the hop is a `podman exec` instead. readme.md, "How git over SSH works
|
||||
# now", is where the reasoning lives.
|
||||
#
|
||||
# Every task here is root-only (users, /usr/local/bin, /etc/ssh, /etc/sudoers),
|
||||
# so each elevates on its own. The play carries no become, because the Quadlet
|
||||
# units have to belong to the connection user.
|
||||
|
||||
# Git-over-SSH uses the host's sshd on port 22, and the shim reaches the container through a one-command sudoers rule.
|
||||
- name: Ensure the git group exists
|
||||
ansible.builtin.group:
|
||||
name: "{{ git_user }}"
|
||||
become: true
|
||||
|
||||
# The shell matters even though nobody ever gets one: sshd runs a forced command
|
||||
# through the login user's shell (`/bin/bash -c '...'`), so a nologin shell would
|
||||
# break git-over-SSH outright.
|
||||
#
|
||||
# The uid is deliberately left to the system. On monoco the host git account was
|
||||
# uid 1003 because the container's git account was 1003 and the two shared one
|
||||
# uid space; under keep-id the container's 1003 is mapped onto {{ podman_user }}
|
||||
# instead, so nothing on this host depends on this number any more — not the
|
||||
# key file (owned by name), not the sudoers rule (matched by name), not the
|
||||
# authorized_keys hook (run as {{ podman_user }}).
|
||||
# sshd runs the forced command through the login user's shell, so it must not be nologin; the uid is left to the system.
|
||||
- name: Add the git login user
|
||||
ansible.builtin.user:
|
||||
name: "{{ git_user }}"
|
||||
@@ -49,11 +16,6 @@
|
||||
create_home: true
|
||||
become: true
|
||||
|
||||
# There is deliberately no ~/.ssh for this user any more. Its old contents were
|
||||
# the shim's client key and the authorized_keys Gitea maintains; the key is
|
||||
# obsolete (nothing authenticates over ssh in this design) and the file lives in
|
||||
# the container's data tree now, where Gitea writes it. The migration notes in
|
||||
# readme.md move the file into place.
|
||||
|
||||
- name: Install the git-over-SSH passthrough shim
|
||||
ansible.builtin.template:
|
||||
@@ -82,9 +44,7 @@
|
||||
mode: '0755'
|
||||
become: true
|
||||
|
||||
# valid with `visudo -cf %s`: a syntax error in /etc/sudoers.d does not fail one
|
||||
# rule, it fails *every* sudo invocation on the host, which on a server reached
|
||||
# by ssh is a nasty way to find out.
|
||||
# A syntax error in /etc/sudoers.d breaks every sudo on the host, so validate before installing.
|
||||
- name: Let the git user reach the container as {{ podman_user }}
|
||||
ansible.builtin.template:
|
||||
src: sudoers-gitea.j2
|
||||
@@ -107,10 +67,7 @@
|
||||
register: gitea_sshd_dropin
|
||||
become: true
|
||||
|
||||
# A drop-in that does not parse is not a failed play, it is a host nobody can
|
||||
# log in to after the next reboot: sshd reads the whole directory at start-up.
|
||||
# Validate the resulting configuration before it is ever loaded, and take the
|
||||
# file away again if it does not parse.
|
||||
# A drop-in that does not parse locks everyone out on the next reboot, so validate it and remove the file if it fails.
|
||||
- name: Validate the resulting sshd configuration
|
||||
ansible.builtin.command: /usr/sbin/sshd -t
|
||||
changed_when: false
|
||||
@@ -130,8 +87,7 @@
|
||||
sshd is still running — and still restarting — on its previous
|
||||
configuration. Run `/usr/sbin/sshd -t` on the host to see why.
|
||||
|
||||
# `reload`, not `restart`: a reload re-execs sshd without dropping the connection
|
||||
# this play is running over.
|
||||
# A reload re-execs sshd without dropping the connection this play runs over.
|
||||
- name: Reload sshd
|
||||
ansible.builtin.systemd_service:
|
||||
name: "{{ sshd_service }}"
|
||||
|
||||
+15
-69
@@ -1,114 +1,60 @@
|
||||
---
|
||||
# ---------------------------------------------------------------------------
|
||||
# Rootless Podman / Quadlet
|
||||
# ---------------------------------------------------------------------------
|
||||
# Duplicated on purpose from caddy/vars/default.yml: a play cannot include that
|
||||
# file wholesale, because it also sets `host_directory` — to the Caddy data
|
||||
# directory — and every playbook defines that for itself. Keep these three in
|
||||
# sync with caddy/vars/default.yml. (Its fourth, podman_unprivileged_port_start,
|
||||
# belongs to the podman tasks, which this play does not run: Gitea publishes
|
||||
# nothing host-side.)
|
||||
#
|
||||
# podman_user is derived from the connection: this play carries no become at
|
||||
# play level, so the Quadlet units belong to whoever Ansible connects as.
|
||||
# Requires gather_facts (set in playbook.yml).
|
||||
# Duplicated from caddy/vars/default.yml on purpose, so keep them in sync.
|
||||
# podman_user comes from the connection user, so the play needs gather_facts.
|
||||
podman_user: "{{ ansible_facts['user_id'] }}"
|
||||
podman_data_dir: "{{ ansible_facts['user_dir'] }}/podman-data"
|
||||
quadlet_dir: "{{ ansible_facts['user_dir'] }}/.config/containers/systemd"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Gitea
|
||||
# ---------------------------------------------------------------------------
|
||||
host: git.tanshu.com
|
||||
|
||||
container_name: gitea
|
||||
unit_name: "{{ container_name }}.service"
|
||||
|
||||
# Fully qualified on purpose: rootless Podman resolves short names against
|
||||
# unqualified-search-registries, and there is no TTY to answer a prompt when
|
||||
# the systemd unit starts.
|
||||
# Fully qualified because rootless Podman would otherwise prompt for a registry, and a unit has no TTY.
|
||||
image: docker.io/gitea/gitea:latest
|
||||
|
||||
# The Quadlet file is <network_name>.network. caddy/roles/register pins the
|
||||
# Podman network name to <network_name>_net (so: gitea.network, gitea_net).
|
||||
# caddy/roles/register pins the Podman network to <network_name>_net, so the Quadlet file is gitea.network.
|
||||
network_name: "{{ container_name }}"
|
||||
|
||||
host_directory: "{{ podman_data_dir }}/{{ container_name }}"
|
||||
|
||||
# Port inside the container that Caddy proxies to — app.ini's HTTP_PORT. Not
|
||||
# published on the host: Caddy reaches it by container name.
|
||||
# The port Caddy proxies to inside the container, where app.ini's HTTP_PORT listens. Nothing is published on the host.
|
||||
container_port: 3000
|
||||
|
||||
# The uid/gid of the `git` account the image creates for itself
|
||||
# (git:x:1003:1003, verified in the image), and therefore the uid Gitea runs as.
|
||||
# The number is load-bearing three times over:
|
||||
#
|
||||
# * UserNS in the Quadlet unit maps it onto podman_user, which is what keeps
|
||||
# every file Gitea writes owned by podman_user on the host — plain tar and
|
||||
# rsync backups, no subuids;
|
||||
# * USER_UID/USER_GID force the entrypoint to keep it, so the file layout and
|
||||
# the mapping cannot drift apart;
|
||||
# * roles/ssh execs into the container as exactly this uid.
|
||||
#
|
||||
# Change one and the other two have to change with it.
|
||||
# The uid/gid of the image's `git` account, and therefore the uid Gitea runs as.
|
||||
# UserNS maps it onto podman_user, USER_UID/GID keep it, and roles/ssh execs as it, so change all three together.
|
||||
gitea_uid: 1003
|
||||
gitea_gid: 1003
|
||||
|
||||
# Where the image keeps its data *inside* the container, and therefore the
|
||||
# GITEA_CUSTOM the image's own environment already sets.
|
||||
# The image's data directory inside the container, and the GITEA_CUSTOM it already sets.
|
||||
gitea_custom: /data/gitea
|
||||
|
||||
# Gitea's own unauthenticated health endpoint. The image ships no HEALTHCHECK,
|
||||
# so the unit defines one from this and the play gates on it.
|
||||
# The image ships no HEALTHCHECK, so the unit defines one from this endpoint and the play gates on it.
|
||||
health_cmd: "curl -fsS -o /dev/null http://127.0.0.1:{{ container_port }}/api/healthz"
|
||||
|
||||
# Only log timestamps are affected: Gitea stores each user's own timezone. The
|
||||
# Docker-era container bind-mounted the host's /etc/localtime and /etc/timezone
|
||||
# instead; TZ is the same intent without depending on either file existing.
|
||||
# Only log timestamps are affected: Gitea stores each user's own timezone.
|
||||
timezone: Asia/Kolkata
|
||||
|
||||
# A scratch directory for the sshd *inside* the image, which this deployment
|
||||
# does not use but which still has to write host keys somewhere. It is kept
|
||||
# outside the data tree on purpose: the process that runs it is the container's
|
||||
# root, which under keep-id is a subuid, and a subuid-owned file inside
|
||||
# {{ host_directory }} would break both a plain tar backup and the play's
|
||||
# "nothing in here belongs to another user" check. See readme.md.
|
||||
# The in-image sshd needs host keys somewhere, but it runs as a subuid, so keep them outside the data tree.
|
||||
container_sshd_hostkeys: "{{ podman_data_dir }}/{{ container_name }}-sshd"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The git-over-SSH entry point on the host
|
||||
# ---------------------------------------------------------------------------
|
||||
# Clients keep using git@git.tanshu.com:user/repo.git on port 22, served by the
|
||||
# *host's* sshd, exactly as they did on monoco. No sshd runs inside the
|
||||
# container: under keep-id the container's root is a subuid that cannot read the
|
||||
# authorized_keys Gitea writes as podman_user, so the second hop is a `podman
|
||||
# exec` instead of an ssh. See readme.md, "How git over SSH works now".
|
||||
#
|
||||
# `git_home` only has to exist — sshd runs the forced command from it — and its
|
||||
# uid is deliberately left to the system: nothing in this design pairs the host
|
||||
# account with the container's uid. See roles/ssh/tasks/main.yaml.
|
||||
# Clients keep using git@git.tanshu.com:user/repo.git on port 22, served by the host's sshd.
|
||||
# `git_home` only has to exist, and its uid is left to the system.
|
||||
git_user: git
|
||||
git_home: /home/git
|
||||
|
||||
# The command Gitea writes into every authorized_keys line it maintains. This is
|
||||
# a contract, not a knob: it is already baked into the lines sitting in the file
|
||||
# copied from monoco, and renaming it locks every user out of git-over-SSH until
|
||||
# Gitea rewrites them. See roles/ssh/templates/gitea.j2.
|
||||
# Renaming this path locks users out because every authorized_keys line Gitea writes already contains it.
|
||||
shim_path: /usr/local/bin/gitea
|
||||
|
||||
# Runs as podman_user, via the sudoers drop-in, and does the podman exec.
|
||||
# Runs as podman_user through the sudoers drop-in and does the podman exec.
|
||||
podman_exec_wrapper: /usr/local/bin/gitea-container-exec
|
||||
|
||||
# What sshd calls to obtain the git user's authorized_keys.
|
||||
authorized_keys_command: /usr/local/bin/gitea-authorized-keys
|
||||
|
||||
sshd_dropin_path: /etc/ssh/sshd_config.d/60-gitea.conf
|
||||
sshd_service: ssh
|
||||
sudoers_path: /etc/sudoers.d/gitea-ssh-passthrough
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The shared Caddy unit and its Caddyfile, both owned by caddy/playbook.yml
|
||||
# ---------------------------------------------------------------------------
|
||||
caddy_name: caddy
|
||||
caddyfile_path: "{{ podman_data_dir }}/{{ caddy_name }}/conf/Caddyfile"
|
||||
|
||||
|
||||
Reference in new issue
Block a user