From 7df93313e723c053cfa69feb21bc98fa9f738243 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Tue, 28 Oct 2025 18:12:53 +0100 Subject: [PATCH 01/16] feat/proxy-certificate-integration (#204) --- .gitignore | 3 +- base/default.yml | 7 +- base/roles/base/tasks/main.yml | 10 +-- base/roles/base/vars/main.yml | 2 + libs/proxy/attributes/default.rb | 8 ++- libs/proxy/config.env | 1 + .../default/config/10-assistant-example.caddy | 4 -- .../files/default/config/10-assistant.caddy | 19 ++++++ libs/proxy/recipes/default.rb | 19 ++++-- libs/proxy/templates/Caddyfile.erb | 65 +++++++++++-------- local/Dockerfile | 5 +- 11 files changed, 92 insertions(+), 51 deletions(-) delete mode 100644 libs/proxy/files/default/config/10-assistant-example.caddy create mode 100644 libs/proxy/files/default/config/10-assistant.caddy diff --git a/.gitignore b/.gitignore index a80cf3b..e501d5c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ local/*.hash # git add --force '**/*.local*' -*.local.caddy +*.local.* +!.*.local.* diff --git a/base/default.yml b/base/default.yml index 002a14b..208f359 100644 --- a/base/default.yml +++ b/base/default.yml @@ -4,13 +4,16 @@ gather_facts: no vars: os: "{{ OS | default('local:vztmpl/debian-13-standard_13.1-1_amd64.tar.zst') }}" - key_dir: "{{ KEYS_DIR | default('/share/.ssh') }}" + share_dir: "{{ SHARE | default('/share') }}" + cert_dir: "{{ share_dir }}/.cert" + key_dir: "{{ share_dir }}/.ssh" tasks: - - name: Ensure key directory + - name: Ensure directories file: path: "{{ key_dir }}" state: directory + loop: ["{{ share_dir }}", "{{ cert_dir }}", "{{ key_dir }}"] - name: Generate container key on host community.crypto.openssh_keypair: diff --git a/base/roles/base/tasks/main.yml b/base/roles/base/tasks/main.yml index c011dcd..4687316 100644 --- a/base/roles/base/tasks/main.yml +++ b/base/roles/base/tasks/main.yml @@ -1,8 +1,9 @@ - name: Base container configuration block: - - name: Set key directory + - name: Set shared directories set_fact: - key_dir: "{{ KEYS_DIR | default('/share/.ssh') }}" + cert_dir: "{{ share_dir }}/.certs" + key_dir: "{{ share_dir }}/.ssh" - name: Update system apt: @@ -51,8 +52,9 @@ include_tasks: state.yml vars: extra: - - { path: "/app", state: "directory", mode: "0755", owner: "app", group: "config" } - - { path: "/app/.ssh", state: "directory", mode: "0711", owner: "app", group: "config" } + - { path: "/app/.ssh", state: "directory", mode: "0755", owner: "app", group: "config" } + - { path: "{{ key_dir }}", state: "directory", mode: "0711", owner: "app", group: "config" } + - { path: "{{ cert_dir }}", state: "directory", mode: "0711", owner: "app", group: "config" } - name: Container accessibility import_tasks: access.yml diff --git a/base/roles/base/vars/main.yml b/base/roles/base/vars/main.yml index 8ce4178..3b0abc9 100644 --- a/base/roles/base/vars/main.yml +++ b/base/roles/base/vars/main.yml @@ -11,5 +11,7 @@ default_users: - { name: "app", groups: ["config"], create_home: false, home: "/app" } - { name: "config", groups: ["config", "root", "sudo"], create_home: false, home: "/app" } +share_dir: "/share" + ssh_users: - config diff --git a/libs/proxy/attributes/default.rb b/libs/proxy/attributes/default.rb index f5f1f2f..0e358a2 100644 --- a/libs/proxy/attributes/default.rb +++ b/libs/proxy/attributes/default.rb @@ -4,11 +4,13 @@ default['app']['group'] = Default.group(node) default['proxy']['dir']['app'] = '/app/proxy' +default['proxy']['dir']['certs'] = '/share/.certs' +default['proxy']['dir']['caddy'] = "#{node['proxy']['dir']['certs']}/caddy" default['proxy']['dir']['config'] = '/app/proxy/conf.d' default['proxy']['dir']['logs'] = '/app/proxy/logs' -default['proxy']['config']['domain'] = 'lan' +default['proxy']['config']['domain'] = 'l' default['proxy']['logs']['roll_size'] = '2MiB' -default['proxy']['logs']['roll_keep'] = '3' -default['proxy']['logs']['roll_for'] = '1d' +default['proxy']['logs']['roll_keep'] = '7' +default['proxy']['logs']['roll_for'] = '24h' diff --git a/libs/proxy/config.env b/libs/proxy/config.env index 426f458..aafe062 100644 --- a/libs/proxy/config.env +++ b/libs/proxy/config.env @@ -4,4 +4,5 @@ CORES="2" MEMORY="2048" SWAP="512" DISK="local-lvm:2" +MOUNT="share" BOOT="yes" \ No newline at end of file diff --git a/libs/proxy/files/default/config/10-assistant-example.caddy b/libs/proxy/files/default/config/10-assistant-example.caddy deleted file mode 100644 index e53b918..0000000 --- a/libs/proxy/files/default/config/10-assistant-example.caddy +++ /dev/null @@ -1,4 +0,0 @@ -# http: -# use_x_forwarded_for: true -# trusted_proxies: -# - # e. g. 192.168.178.101 diff --git a/libs/proxy/files/default/config/10-assistant.caddy b/libs/proxy/files/default/config/10-assistant.caddy new file mode 100644 index 0000000..6548edb --- /dev/null +++ b/libs/proxy/files/default/config/10-assistant.caddy @@ -0,0 +1,19 @@ +# *-container.local.caddy (.gitignore): create, e. g. home.gitops.pm +# +# home.gitops.pm { +# import default api 192.178.168.110 +# tls /share/.certs/.lego/certificates/gitops.pm.crt /share/.certs/.lego/certificates/gitops.pm.key +# .. } + +# *-container.caddy: edit, e. g. assistant (10-assistant.caddy) + +route { + reverse_proxy @internal {vars.upstream}:8123 +} + + +# Attachment: Home Assistant configuration +# http: +# use_x_forwarded_for: true +# trusted_proxies: +# - # e. g. 192.168.178.101 diff --git a/libs/proxy/recipes/default.rb b/libs/proxy/recipes/default.rb index 01ca71e..08b3d70 100644 --- a/libs/proxy/recipes/default.rb +++ b/libs/proxy/recipes/default.rb @@ -1,6 +1,7 @@ Env.dump(self, ['ip', cookbook_name], repo: cookbook_name) -Common.directories(self, [node['proxy']['dir']['app'], node['proxy']['dir']['config'], node['proxy']['dir']['logs']]) +Common.directories(self, [ node['proxy']['dir']['app'], + node['proxy']['dir']['caddy'], node['proxy']['dir']['config'], node['proxy']['dir']['logs'] ] ) package 'caddy' @@ -20,7 +21,8 @@ owner node['app']['user'] group node['app']['group'] mode '0644' - variables( hosts: lazy { node.run_state['proxy_hosts'] || [] }, config_dir: node['proxy']['dir']['config'], + variables( hosts: lazy { node.run_state['proxy_hosts'] || [] }, + caddy_dir: node['proxy']['dir']['caddy'], config_dir: node['proxy']['dir']['config'], log_dir: node['proxy']['dir']['logs'], logs_roll_size: node['proxy']['logs']['roll_size'], logs_roll_keep: node['proxy']['logs']['roll_keep'], logs_roll_for: node['proxy']['logs']['roll_for'] ) end @@ -29,10 +31,13 @@ source 'config' owner node['app']['user'] group node['app']['group'] - mode '0664' + mode '0775' + files_mode '0664' end -Common.application(self, cookbook_name, - exec: "/bin/caddy run --config #{node['proxy']['dir']['app']}/Caddyfile --adapter caddyfile", - subscribe: ["template[#{node['proxy']['dir']['app']}/Caddyfile]", "remote_directory[#{node['proxy']['dir']['config']}]"], - unit: { 'Service' => { 'AmbientCapabilities' => 'CAP_NET_BIND_SERVICE' } } ) +ruby_block "#{self.cookbook_name}_application" do block do + Common.application(self, cookbook_name, + exec: "/bin/caddy run --config #{node['proxy']['dir']['app']}/Caddyfile", + subscribe: ["template[#{node['proxy']['dir']['app']}/Caddyfile]", "remote_directory[#{node['proxy']['dir']['config']}]"], + unit: { 'Service' => { 'AmbientCapabilities' => 'CAP_NET_BIND_SERVICE' } } ) +end end diff --git a/libs/proxy/templates/Caddyfile.erb b/libs/proxy/templates/Caddyfile.erb index 727bbdb..bb62f34 100644 --- a/libs/proxy/templates/Caddyfile.erb +++ b/libs/proxy/templates/Caddyfile.erb @@ -1,11 +1,14 @@ +{ + storage file_system <%= @caddy_dir %> +} + (internal) { - @external { - not remote_ip 192.168.0.0/24 - } - respond @external 403 + @internal remote_ip 192.168.178.0/24 + @external not remote_ip 192.168.178.0/24 + respond @external "Forbidden" 403 } -(security_headers) { +(header) { header { Strict-Transport-Security "max-age=31536000;" X-Frame-Options "DENY" @@ -15,34 +18,40 @@ } } -(proxy_headers) { - header_up Host {host} - header_up X-Real-IP {remote_ip} - header_up X-Forwarded-For {remote_ip} - header_up X-Forwarded-Proto {scheme} +(common) { + import header + + log { + output file <%= @log_dir %>/{args.0}.log { + roll_size <%= @logs_roll_size %> + roll_keep <%= @logs_roll_keep %> + roll_keep_for <%= @logs_roll_for %> + } + } +} + +(default) { + import common {args.0} + + vars upstream {args.1} + + reverse_proxy {args.1} { + header_up Host {args.0} + header_up X-Real-IP {remote_ip} + header_up X-Forwarded-For {remote_ip} + header_up X-Container-IP {args.1} + } } -<% @hosts.each do |entry| -%> - <% domain, upstream, hostname = entry.split(' ') -%> +<% @hosts.each do |entry| -%> <% domain, upstream, hostname = entry.split(' ') -%> <%= domain %> { - import security_headers + import default <%= hostname %> <%= upstream %> import internal - reverse_proxy <%= upstream %> { - import proxy_headers - header_up X-Container-IP <%= upstream.split(':').first %> - } - tls internal - log { - output file <%= @log_dir %>/<%= domain %>.log { - roll_size <%= @logs_roll_size %> - roll_keep <%= @logs_roll_keep %> - roll_keep_for <%= @logs_roll_for %> - } - } - - import <%= @config_dir %>/<%= hostname %>*.caddy + import <%= @config_dir %>/*<%= hostname %>.caddy } -<% end -%> \ No newline at end of file +<% end -%> + +import <%= @config_dir %>/*.local.caddy diff --git a/local/Dockerfile b/local/Dockerfile index 5c59ae0..0efd02c 100644 --- a/local/Dockerfile +++ b/local/Dockerfile @@ -22,11 +22,12 @@ RUN rm -rf /lib/systemd/system/multi-user.target.wants/* && \ RUN ansible-galaxy collection install community.general --force -RUN mkdir -p /app/.ssh /share/.ssh && ssh-keygen -t ed25519 -f "/share/.ssh/${ID}" -N '' +RUN mkdir -p /app/.ssh /share/.certs /share/.ssh +RUN ssh-keygen -t ed25519 -f "/share/.ssh/${ID}" -N '' COPY ../base/roles /tmp/config/base RUN ansible localhost -m include_role -a name=base \ - -e "ip=${IP}" -e "id=${ID}" -e "KEYS_DIR=/share/.ssh" -e "configure_ssh=0" -e "arch=${TARGETARCH}" \ + -e "ip=${IP}" -e "id=${ID}" -e "SHARE=/share" -e "configure_ssh=0" -e "arch=${TARGETARCH}" \ -e "private_key='$(cat /share/.ssh/${ID})\n'" -e "public_key='$(cat /share/.ssh/${ID}.pub)\n'" RUN chown -R app:config /app From d2d8d84a15f18c477410b052c33c0815eb6c65fc Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Wed, 29 Oct 2025 08:42:34 +0100 Subject: [PATCH 02/16] chore/prepare-version (#201) --- config/attributes/default.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/attributes/default.rb b/config/attributes/default.rb index 37532ca..64df13a 100644 --- a/config/attributes/default.rb +++ b/config/attributes/default.rb @@ -1,6 +1,6 @@ default['title'] = "Proxmox-GitOps" default['online'] = "https://github.com/stevius10/Proxmox-GitOps" -default['version'] = "v1.2-2" +default['version'] = "v1.2-3" default['id'] = ENV['ID'] default['host'] = (default['ip'] = ENV['IP'].to_s.presence || "127.0.0.1") From 321a446b137972cd6b7ad79df0e353c5830fbd38 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Wed, 29 Oct 2025 08:43:20 +0100 Subject: [PATCH 03/16] chore/profile-update-alias (#205) --- base/roles/base/files/profile.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/base/roles/base/files/profile.sh b/base/roles/base/files/profile.sh index ee27d08..c190759 100644 --- a/base/roles/base/files/profile.sh +++ b/base/roles/base/files/profile.sh @@ -7,7 +7,9 @@ alias .....='cd ../../../..' # General +alias c='cd' alias l='ls -lhA --group-directories-first' +alias s='systemctl' alias grep='grep --color=auto' alias mdir='mkdir -pv' @@ -73,6 +75,14 @@ extract () { fi } +exe() { + docker exec -it "$(docker ps -qf name=$1)" /bin/bash +} + +j() { + journalctl -xe --no-pager -u "$1" || journalctl -xe --no-pager +} + package() { local project project=$(basename "$PWD") @@ -93,4 +103,4 @@ package() { printf "\n---\n\n" fi done > "$out" <<< "$file_list" -} +} \ No newline at end of file From 0cc4597007aa06ba234ac2f7f53558b72eff5b7c Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Wed, 29 Oct 2025 15:58:05 +0100 Subject: [PATCH 04/16] feat/proxy-initial-trust-as-root (#206) --- base/roles/base/tasks/main.yml | 3 ++- libs/proxy/attributes/default.rb | 25 +++++++++++++------------ libs/proxy/recipes/default.rb | 18 ++++++++++++++---- libs/proxy/templates/Caddyfile.erb | 10 ++++++++-- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/base/roles/base/tasks/main.yml b/base/roles/base/tasks/main.yml index 4687316..14b9294 100644 --- a/base/roles/base/tasks/main.yml +++ b/base/roles/base/tasks/main.yml @@ -52,7 +52,8 @@ include_tasks: state.yml vars: extra: - - { path: "/app/.ssh", state: "directory", mode: "0755", owner: "app", group: "config" } + - { path: "/app", state: "directory", mode: "0755", owner: "app", group: "config" } + - { path: "/app/.ssh", state: "directory", mode: "0711", owner: "app", group: "config" } - { path: "{{ key_dir }}", state: "directory", mode: "0711", owner: "app", group: "config" } - { path: "{{ cert_dir }}", state: "directory", mode: "0711", owner: "app", group: "config" } diff --git a/libs/proxy/attributes/default.rb b/libs/proxy/attributes/default.rb index 0e358a2..b0d769a 100644 --- a/libs/proxy/attributes/default.rb +++ b/libs/proxy/attributes/default.rb @@ -1,16 +1,17 @@ -default['ip'] = ENV['IP'] +default['ip'] = ENV['IP'] -default['app']['user'] = Default.user(node) -default['app']['group'] = Default.group(node) +default['app']['user'] = Default.user(node) +default['app']['group'] = Default.group(node) -default['proxy']['dir']['app'] = '/app/proxy' -default['proxy']['dir']['certs'] = '/share/.certs' -default['proxy']['dir']['caddy'] = "#{node['proxy']['dir']['certs']}/caddy" -default['proxy']['dir']['config'] = '/app/proxy/conf.d' -default['proxy']['dir']['logs'] = '/app/proxy/logs' +default['proxy']['dir']['app'] = '/app/proxy' +default['proxy']['dir']['certs'] = '/share/.certs' +default['proxy']['dir']['caddy'] = "#{node['proxy']['dir']['certs']}/caddy" +default['proxy']['dir']['config'] = '/app/proxy/conf.d' +default['proxy']['dir']['logs'] = '/app/proxy/logs' -default['proxy']['config']['domain'] = 'l' +default['proxy']['config']['domain'] = 'l' +default['proxy']['config']['internal'] = '192.168.178.0/24' -default['proxy']['logs']['roll_size'] = '2MiB' -default['proxy']['logs']['roll_keep'] = '7' -default['proxy']['logs']['roll_for'] = '24h' +default['proxy']['logs']['roll_size'] = '2MiB' +default['proxy']['logs']['roll_keep'] = '7' +default['proxy']['logs']['roll_for'] = '24h' diff --git a/libs/proxy/recipes/default.rb b/libs/proxy/recipes/default.rb index 08b3d70..a5b7039 100644 --- a/libs/proxy/recipes/default.rb +++ b/libs/proxy/recipes/default.rb @@ -21,9 +21,9 @@ owner node['app']['user'] group node['app']['group'] mode '0644' - variables( hosts: lazy { node.run_state['proxy_hosts'] || [] }, - caddy_dir: node['proxy']['dir']['caddy'], config_dir: node['proxy']['dir']['config'], - log_dir: node['proxy']['dir']['logs'], logs_roll_size: node['proxy']['logs']['roll_size'], + variables( hosts: lazy { node.run_state['proxy_hosts'] || [] }, config_dir: node['proxy']['dir']['config'], + caddy_dir: node['proxy']['dir']['caddy'], log_dir: node['proxy']['dir']['logs'], + internal: node['proxy']['config']['internal'], logs_roll_size: node['proxy']['logs']['roll_size'], logs_roll_keep: node['proxy']['logs']['roll_keep'], logs_roll_for: node['proxy']['logs']['roll_for'] ) end @@ -35,8 +35,18 @@ files_mode '0664' end +execute "#{self.cookbook_name}_initialize" do + command "/bin/caddy trust --config #{node['proxy']['dir']['app']}/Caddyfile" + user 'root' + timeout 120 + not_if { ::File.directory?("#{node['proxy']['dir']['caddy']}/certificates") || + ::File.directory?("#{node['proxy']['dir']['caddy']}/pki") } + subscribes :run, "template[#{node['proxy']['dir']['app']}/Caddyfile]", :immediately + action :nothing +end + ruby_block "#{self.cookbook_name}_application" do block do - Common.application(self, cookbook_name, + Common.application(self, cookbook_name, actions: [:start, :enable], exec: "/bin/caddy run --config #{node['proxy']['dir']['app']}/Caddyfile", subscribe: ["template[#{node['proxy']['dir']['app']}/Caddyfile]", "remote_directory[#{node['proxy']['dir']['config']}]"], unit: { 'Service' => { 'AmbientCapabilities' => 'CAP_NET_BIND_SERVICE' } } ) diff --git a/libs/proxy/templates/Caddyfile.erb b/libs/proxy/templates/Caddyfile.erb index bb62f34..e4c5037 100644 --- a/libs/proxy/templates/Caddyfile.erb +++ b/libs/proxy/templates/Caddyfile.erb @@ -3,8 +3,8 @@ } (internal) { - @internal remote_ip 192.168.178.0/24 - @external not remote_ip 192.168.178.0/24 + @internal remote_ip <%= @internal %> + @external not remote_ip <%= @internal %> respond @external "Forbidden" 403 } @@ -51,6 +51,12 @@ tls internal import <%= @config_dir %>/*<%= hostname %>.caddy + + route { + reverse_proxy @internal <%= upstream %> { + trusted_proxies <%= @internal %> + } + } } <% end -%> From dd4266ea2df56ff879e974d3983e34c2babc6e09 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Wed, 29 Oct 2025 16:03:01 +0100 Subject: [PATCH 05/16] chore/base-default-packages-jq (#207) --- base/roles/base/vars/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/base/roles/base/vars/main.yml b/base/roles/base/vars/main.yml index 3b0abc9..00e0ee3 100644 --- a/base/roles/base/vars/main.yml +++ b/base/roles/base/vars/main.yml @@ -2,6 +2,7 @@ default_packages: - sudo - locales - curl + - jq - unzip - vim From 3e5b1e500b47739ea0a91b5c0928fa3d09dfb14f Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Wed, 29 Oct 2025 16:35:56 +0100 Subject: [PATCH 06/16] refactor/libraries-application-systemctl (#208) --- config/libraries/common.rb | 30 ++++++++++++++++++------------ config/recipes/runner.rb | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/config/libraries/common.rb b/config/libraries/common.rb index 4c02cdb..0af9b7f 100644 --- a/config/libraries/common.rb +++ b/config/libraries/common.rb @@ -1,3 +1,5 @@ +require_relative 'default' + module Common # General @@ -33,14 +35,10 @@ def self.daemon(ctx, name) end end - def self.application(ctx, name, user: nil, group: nil, + def self.application(ctx, name, user: Default.user(ctx).to_s, group: Default.group(ctx).to_s, exec: nil, cwd: nil, unit: {}, actions: [:enable, :start], subscribe: nil, reload: 'systemd_reload', restart: 'on-failure', restart_delay: 10, restart_limit: 10, restart_max: 600, verify: true, verify_timeout: 60, verify_interval: 5, verify_cmd: "systemctl is-active --quiet #{name}") - user ||= Default.user(ctx) - group ||= Default.group(ctx) - user = user.to_s - group = group.to_s if exec daemon(ctx, reload) @@ -69,7 +67,7 @@ def self.application(ctx, name, user: nil, group: nil, # Mask default application service conflicts = %Q(systemctl list-unit-files '*#{File.basename(exec.split.first)}*.service' --no-legend | awk '$2!="masked" {print $1}') - Ctx.dsl(ctx).execute "mask_conflicts_#{name}" do + Ctx.dsl(ctx).execute "application_mask_#{name}" do command "#{conflicts} | xargs -r -IUNIT sh -c 'systemctl stop UNIT && systemctl mask UNIT'" only_if conflicts returns [0, 123] # already masked returns '123' @@ -81,15 +79,22 @@ def self.application(ctx, name, user: nil, group: nil, group 'root' mode '0664' content unit_content + notifies :run, "execute[application_reset_#{name}]", :immediately notifies :run, "execute[#{reload}]", :immediately notifies :restart, "service[#{name}]", :delayed end end + Ctx.dsl(ctx).execute "application_reset_#{name}" do + command "systemctl reset-failed #{name}.service" + only_if "systemctl is-failed --quiet #{name}.service" + action :nothing + end + if actions.include?(:force_restart) - Ctx.dsl(ctx).execute "force_restart_#{name}" do - command "systemctl reset-failed #{name}; systemctl stop #{name} || true && sleep 1 && systemctl start #{name}" + Ctx.dsl(ctx).execute "application_restart_#{name}" do + command "systemctl stop #{name} || true && sleep 1 && systemctl start #{name}" action :run end else @@ -107,11 +112,12 @@ def self.application(ctx, name, user: nil, group: nil, (is_active = Mixlib::ShellOut.new(verify_cmd)).run_command is_active.exitstatus.zero? ? (ok = true; break) : (sleep verify_interval) end - Logs.error!("service '#{name}' failed health check") unless ok + raise (Logs.debug("service '#{name}' failed health check", [ + Mixlib::ShellOut.new("systemctl status #{name} --no-pager").run_command.stdout.strip, + Mixlib::ShellOut.new("journalctl -u #{name} --no-pager").run_command.stdout.strip, + ], level: :error)) unless ok end - action :nothing - subscribes :run, "service[#{name}]", :delayed if verify - subscribes :run, "file[/etc/systemd/system/#{name}.service]", :delayed if verify + only_if { verify } end end diff --git a/config/recipes/runner.rb b/config/recipes/runner.rb index baa7a1b..b444bca 100644 --- a/config/recipes/runner.rb +++ b/config/recipes/runner.rb @@ -9,7 +9,7 @@ Utils.wait("http://localhost:#{node['git']['port']['http']}") - Common.application(self, self.recipe_name, user: node['app']['user'] , actions: [:enable], cwd: node['runner']['dir']['app'], + Common.application(self, self.recipe_name, user: node['app']['user'] , actions: [:start, :enable], cwd: node['runner']['dir']['app'], exec: "#{node['runner']['dir']['app']}/#{self.recipe_name} daemon --config #{node['runner']['dir']['app']}/config.yaml", subscribe: ["template[#{node['runner']['dir']['app']}/config.yaml]", "remote_file[#{node['runner']['dir']['app']}/#{self.recipe_name}]"] ) From 6c4048a630591df1cdc9580bc78bb01e3de9c91c Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sat, 1 Nov 2025 17:36:09 +0100 Subject: [PATCH 07/16] chore/profile-dynamic-shortcuts (#209) --- base/roles/base/files/profile.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/base/roles/base/files/profile.sh b/base/roles/base/files/profile.sh index c190759..5b04c70 100644 --- a/base/roles/base/files/profile.sh +++ b/base/roles/base/files/profile.sh @@ -7,7 +7,6 @@ alias .....='cd ../../../..' # General -alias c='cd' alias l='ls -lhA --group-directories-first' alias s='systemctl' alias grep='grep --color=auto' @@ -56,8 +55,6 @@ backport() { # Functions -cdir() { mkdir "$1" && cd "$1"; } - extract () { if [ -f "$1" ] ; then case "$1" in @@ -79,10 +76,21 @@ exe() { docker exec -it "$(docker ps -qf name=$1)" /bin/bash } +c() { + [ -z "$1" ] && { cd; return; } + [ -d "$1" ] && { cd "$1"; return; } || + [ -f "$1" ] && file -b "$1" | grep -q -e "text" -e "empty" && { cat "$1"; return; } || + file "$1" +} + j() { journalctl -xe --no-pager -u "$1" || journalctl -xe --no-pager } +m() { + mkdir "$1" && cd "$1"; +} + package() { local project project=$(basename "$PWD") From 6210fb4be5d925e725cee69e71d04c5b350d45d4 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sat, 1 Nov 2025 18:53:29 +0100 Subject: [PATCH 08/16] fix/proxy-unit-wants-share (#210) --- libs/proxy/recipes/default.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/proxy/recipes/default.rb b/libs/proxy/recipes/default.rb index a5b7039..7cbf924 100644 --- a/libs/proxy/recipes/default.rb +++ b/libs/proxy/recipes/default.rb @@ -49,5 +49,6 @@ Common.application(self, cookbook_name, actions: [:start, :enable], exec: "/bin/caddy run --config #{node['proxy']['dir']['app']}/Caddyfile", subscribe: ["template[#{node['proxy']['dir']['app']}/Caddyfile]", "remote_directory[#{node['proxy']['dir']['config']}]"], - unit: { 'Service' => { 'AmbientCapabilities' => 'CAP_NET_BIND_SERVICE' } } ) + unit: { 'Unit': { 'Wants' => 'share.service', 'After' => 'network.target share.service' }, + 'Service' => { 'AmbientCapabilities' => 'CAP_NET_BIND_SERVICE' } } ) end end From 26cf078640e5e9a26916b69d5c33f1a802e24a75 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sun, 2 Nov 2025 09:03:41 +0100 Subject: [PATCH 09/16] chore/profile-shortcuts-dynamic-systemctl (#211) --- base/roles/base/files/profile.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/base/roles/base/files/profile.sh b/base/roles/base/files/profile.sh index 5b04c70..be28ef6 100644 --- a/base/roles/base/files/profile.sh +++ b/base/roles/base/files/profile.sh @@ -91,6 +91,15 @@ m() { mkdir "$1" && cd "$1"; } +s() { + [ -z "$1" ] && { cd /etc/systemd/system; return $?; } + case "$1" in start|stop|restart|reload|enable|disable|status|is-active|is-enabled|is-failed|mask|unmask|daemon-reload|reset-failed| \ + cat|show|edit|list-units|list-unit-files|list-dependencies|list-jobs) + command systemctl "$@"; return $?;; + esac + systemctl cat "$1" && echo && systemctl status --no-pager "$1" +} + package() { local project project=$(basename "$PWD") From 53a21df78a471d36f5553665ddd7563729d7ef79 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sun, 2 Nov 2025 10:07:52 +0100 Subject: [PATCH 10/16] chore/profile-shortcuts-alias-loop (#212) --- base/roles/base/files/profile.sh | 41 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/base/roles/base/files/profile.sh b/base/roles/base/files/profile.sh index be28ef6..1a3c40f 100644 --- a/base/roles/base/files/profile.sh +++ b/base/roles/base/files/profile.sh @@ -7,18 +7,6 @@ alias .....='cd ../../../..' # General -alias l='ls -lhA --group-directories-first' -alias s='systemctl' -alias grep='grep --color=auto' -alias mdir='mkdir -pv' - -alias df='df -h' -alias free='free -h' -alias du='du -h' - -alias journal='journalctl -xef --output=short-iso --no-pager' -alias ports='ss -tulpn' -alias proc='ps aux | grep -v grep | grep -i' alias redo='sudo "$(fc -ln -1)"' # Development @@ -65,10 +53,7 @@ extract () { *.tar) tar xvf "$1" ;; *.tgz) tar xvzf "$1" ;; *.zip) unzip "$1" ;; - *) echo "'$1' failed" ;; esac - else - echo "'$1' no valid file" fi } @@ -83,12 +68,23 @@ c() { file "$1" } -j() { - journalctl -xe --no-pager -u "$1" || journalctl -xe --no-pager +d() { + mkdir -pv "$1" && cd "$1"; +} + +f() { + case "$1" in + /*) grep --color=auto -rni "$1" . ;; + *) find . -iname "*${1:1}*" ;; + esac +} + +l() { + command ls -lAhF --color=auto "$@"; } -m() { - mkdir "$1" && cd "$1"; +j() { + journalctl -xe --no-pager -u "$1" || journalctl -xe --no-pager } s() { @@ -103,8 +99,7 @@ s() { package() { local project project=$(basename "$PWD") - local out="${project}-packaged.txt" - + local out="${project}.txt" rm -f -- "$out" if [ -d .git ]; then @@ -115,9 +110,9 @@ package() { while IFS= read -r file; do if file --mime-type --brief "$file" | grep -q '^text/'; then - printf "# Filename: %s\n\n" "$file" + printf "# %s\n\n" "$file" sed '' "$file" printf "\n---\n\n" fi done > "$out" <<< "$file_list" -} \ No newline at end of file +} From 8f0cb47a814bbd43d8167df7626998bb66202590 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sun, 2 Nov 2025 10:43:55 +0100 Subject: [PATCH 11/16] chore/profile-shortcuts-idiomatic-process (#213) --- base/roles/base/files/profile.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/base/roles/base/files/profile.sh b/base/roles/base/files/profile.sh index 1a3c40f..87a9d83 100644 --- a/base/roles/base/files/profile.sh +++ b/base/roles/base/files/profile.sh @@ -87,6 +87,13 @@ j() { journalctl -xe --no-pager -u "$1" || journalctl -xe --no-pager } +p() { + [ -z "$1" ] && { ps aux; return $?; } + local search + search="[${1:0:1}]${1:1}" + ps aux | grep --color=auto "$search" +} + s() { [ -z "$1" ] && { cd /etc/systemd/system; return $?; } case "$1" in start|stop|restart|reload|enable|disable|status|is-active|is-enabled|is-failed|mask|unmask|daemon-reload|reset-failed| \ From e619a22c6b89e27738fb49603ed15176dc89e21a Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sun, 2 Nov 2025 20:02:40 +0100 Subject: [PATCH 12/16] chore/boot-order-change-default (#214) --- config.env | 2 +- local/Dockerfile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.env b/config.env index 53b67a8..f041665 100644 --- a/config.env +++ b/config.env @@ -1,5 +1,5 @@ IP="192.168.178.254" -ID="254" +ID="100" CORES="4" MEMORY="6144" SWAP="1024" diff --git a/local/Dockerfile b/local/Dockerfile index 0efd02c..0e592d5 100644 --- a/local/Dockerfile +++ b/local/Dockerfile @@ -3,8 +3,8 @@ FROM debian:trixie ARG TARGETARCH ENV TARGETARCH=${TARGETARCH} -ENV IP=127.0.0.1 ID=254 LC_ALL=C.UTF-8 -ENV ANSIBLE_ROLES_PATH=/tmp/config/base +ENV IP=127.0.0.1 ID=100 LC_ALL=C.UTF-8 +ENV ANSIBLE_ROLES_PATH=/tmp/config/base STOPSIGNAL SIGRTMIN+3 From 4f5799e5861420fafc855c63c17bc3b099f51b59 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sun, 16 Nov 2025 15:32:31 +0100 Subject: [PATCH 13/16] chore/gitea-interface-cleanup (#215) --- config/recipes/git.rb | 3 ++- .../custom/templates/extra_links.tmpl.erb | 13 +++++++---- .../custom/templates/footer.tmpl.erb | 1 + .../custom/templates/header.tmpl.erb | 1 - config/templates/git_app.ini.erb | 22 +++++++++++++++++-- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/config/recipes/git.rb b/config/recipes/git.rb index 76f418e..03d6491 100644 --- a/config/recipes/git.rb +++ b/config/recipes/git.rb @@ -9,7 +9,8 @@ mode '0644' variables(host: node['host'], app_user: node['app']['user'] , ssh_user: node['app']['config'], app_dir: node['git']['dir']['app'], home_dir: node['git']['dir']['home'], - http_port: node['git']['port']['http'], ssh_port: node['git']['port']['ssh'] ) + http_port: node['git']['port']['http'], ssh_port: node['git']['port']['ssh'], + org_main: node['git']['org']['main']) action :create_if_missing end diff --git a/config/templates/custom/templates/extra_links.tmpl.erb b/config/templates/custom/templates/extra_links.tmpl.erb index 13e9a82..af78929 100644 --- a/config/templates/custom/templates/extra_links.tmpl.erb +++ b/config/templates/custom/templates/extra_links.tmpl.erb @@ -1,4 +1,9 @@ -<% (node['git']['org'] || {}).values.compact.each do |org| %> - <%= org %> -<% end %> -monorepo +{{svg "octicon-dot"}} + + diff --git a/config/templates/custom/templates/footer.tmpl.erb b/config/templates/custom/templates/footer.tmpl.erb index 11ec849..accc9d9 100644 --- a/config/templates/custom/templates/footer.tmpl.erb +++ b/config/templates/custom/templates/footer.tmpl.erb @@ -11,6 +11,7 @@ Gitea + Admin \ No newline at end of file diff --git a/config/templates/custom/templates/header.tmpl.erb b/config/templates/custom/templates/header.tmpl.erb index 6a6a4f5..437e294 100644 --- a/config/templates/custom/templates/header.tmpl.erb +++ b/config/templates/custom/templates/header.tmpl.erb @@ -6,4 +6,3 @@ img[src^="{{AppSubUrl}}/avatars/"]{width:1px;height:1px;opacity:0} .ui.avatar,img.avatar,.avatar{width:1px!important;height:1px!important;opacity:0!important} - diff --git a/config/templates/git_app.ini.erb b/config/templates/git_app.ini.erb index 4141989..119c0fc 100644 --- a/config/templates/git_app.ini.erb +++ b/config/templates/git_app.ini.erb @@ -13,6 +13,8 @@ START_SSH_SERVER = true BUILTIN_SSH_SERVER_USER = <%= @ssh_user %> HTTP_ADDR = 0.0.0.0 +LANDING_PAGE = <%= @org_main %> + [database] DB_TYPE = sqlite3 PATH = <%= @app_dir %>/gitea.db @@ -34,7 +36,6 @@ DISABLE_MIGRATIONS = true [ui] ENABLE_USER_HEATMAP = false -ONLY_SHOW_RELEVANT_REPOS = true EXPLORE_PAGING_DEFAULT_SORT = alphabetically [service] @@ -42,6 +43,13 @@ ENABLE_REGISTRATION_CAPTCHA = false DISABLE_GRAVATAR = true ENABLE_FEDERATED_AVATAR = false SHOW_USER_EMAIL = false +SHOW_MILESTONES_DASHBOARD_PAGE = false + +[service.explore] +REQUIRE_SIGNIN_VIEW = true +DISABLE_USERS_PAGE = true +DISABLE_ORGANIZATIONS_PAGE = true +DISABLE_CODE_PAGE = true [avatar] DISABLE_AVATAR = true @@ -58,4 +66,14 @@ GC_ARGS = --aggressive [log] MODE = console -LEVEL = Error \ No newline at end of file +LEVEL = Error + +[cron] +ENABLED = true + +[other] +SHOW_FOOTER_VERSION = false +SHOW_FOOTER_TEMPLATE_LOAD_TIME = false +SHOW_FOOTER_POWERED_BY = false +ENABLE_SITEMAP = false +ENABLE_FEED = false From 24ce5b962ac84343c3114206a9c832226fa18c0e Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Sun, 16 Nov 2025 16:10:15 +0100 Subject: [PATCH 14/16] chore/gitea-compact-navbar (#216) --- config/templates/custom/css/hide.css.erb | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/config/templates/custom/css/hide.css.erb b/config/templates/custom/css/hide.css.erb index 31a3c40..208f7ad 100644 --- a/config/templates/custom/css/hide.css.erb +++ b/config/templates/custom/css/hide.css.erb @@ -1,13 +1,21 @@ #navbar .item[href$="/issues"]{display:none!important} #navbar .item[href$="/pulls"]{display:none!important} -#navbar .item[href$="/milestones"]{display:none!important} #navbar .item[href$="/explore/repos"]{display:none!important} -#navbar .item[href$="/explore/organizations"]{display:none!important} #navbar .item[href$="https://docs.gitea.com"]{display:none!important} -.page-footer:not(#customized-footer){display:none!important} +#navbar svg.octicon-triangle-down{display: none;} +#navbar .text:has(img[src*="/avatars/"]) > * svg {display: inline-block !important;} +#navbar .tw-ml-1{display: none;} + +.navbar-right a[href="/notifications"]{display:none!important} +.navbar-right a[href$="/-/admin"]{display:none!important} +.navbar-right .user-menu a[href="/notifications/subscriptions"]{display:none!important} -.ui.menu .item:has(.resize-for-semibold[data-text="Aktivität"]){display:none!important} .ui.menu .item:has(.resize-for-semibold[data-text="Activity"]){display:none!important} +.ui.grid [class*="five"].wide.column{display:none!important} +.ui.grid [class*="eleven"].wide.column{width: 100%!important;} + #user-heatmap,.total-contributions,.vch__legend{display:none!important} + +.page-footer:not(#customized-footer){display:none!important} From af4196ebb646b197bc5104db8a7f93fe9c8031b0 Mon Sep 17 00:00:00 2001 From: Steven Koch Date: Wed, 19 Nov 2025 17:05:09 +0100 Subject: [PATCH 15/16] chore/git-interface-stripped (#217) --- config/templates/custom/css/hide.css.erb | 41 +++++++++++++------ config/templates/custom/css/logo.css.erb | 8 ++-- .../custom/templates/extra_links.tmpl.erb | 8 ++-- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/config/templates/custom/css/hide.css.erb b/config/templates/custom/css/hide.css.erb index 208f7ad..05bf07c 100644 --- a/config/templates/custom/css/hide.css.erb +++ b/config/templates/custom/css/hide.css.erb @@ -1,21 +1,38 @@ -#navbar .item[href$="/issues"]{display:none!important} -#navbar .item[href$="/pulls"]{display:none!important} -#navbar .item[href$="/explore/repos"]{display:none!important} -#navbar .item[href$="https://docs.gitea.com"]{display:none!important} +/* Navigation */ + +#navbar-logo {display: none !important;} + +#navbar .item[href$="/issues"]{display: none !important;} +#navbar .item[href$="/pulls"]{display: none !important;} +#navbar .item[href$="/explore/repos"]{display: none !important;} +#navbar .item[href$="https://docs.gitea.com"]{display: none !important;} #navbar svg.octicon-triangle-down{display: none;} #navbar .text:has(img[src*="/avatars/"]) > * svg {display: inline-block !important;} #navbar .tw-ml-1{display: none;} -.navbar-right a[href="/notifications"]{display:none!important} -.navbar-right a[href$="/-/admin"]{display:none!important} -.navbar-right .user-menu a[href="/notifications/subscriptions"]{display:none!important} +.navbar-right a[href="/notifications"]{display: none !important;} +.navbar-right a[href$="/-/admin"]{display: none !important;} +.navbar-right .user-menu a[href="/notifications/subscriptions"]{display: none !important;} + +/* View */ + +.ui.menu .item:has(.resize-for-semibold[data-text="Activity"]) {display: none !important;} +.ui.grid [class*="five"].wide.column{display: none !important;} +.ui.grid [class*="eleven"].wide.column{width: 100% !important;} + + +.ui a.item[href*="/projects"] {display: none !important;} +.ui a.item[href*="/packages"] {display: none !important;} +.ui a.item[href*="/teams"] {display: none !important;} +.ui a.item[href*="/worktime"] {display: none !important;} + +/* Mixed */ -.ui.menu .item:has(.resize-for-semibold[data-text="Activity"]){display:none!important} +#user-heatmap,.total-contributions,.vch__legend{display: none !important;} -.ui.grid [class*="five"].wide.column{display:none!important} -.ui.grid [class*="eleven"].wide.column{width: 100%!important;} +button[hx-post*="follow"] {display: none !important;} -#user-heatmap,.total-contributions,.vch__legend{display:none!important} +/* Footer */ -.page-footer:not(#customized-footer){display:none!important} +.page-footer:not(#customized-footer){display: none !important;} diff --git a/config/templates/custom/css/logo.css.erb b/config/templates/custom/css/logo.css.erb index 20f7b6c..55c9d55 100644 --- a/config/templates/custom/css/logo.css.erb +++ b/config/templates/custom/css/logo.css.erb @@ -1,4 +1,4 @@ -#navbar-logo img{display:none!important} -#navbar-logo{display:flex;align-items:center;gap:.5rem} -#navbar-logo::after{content:"<%= @title %>";font-weight:600;font-size:1.05rem;line-height:1;color:inherit;letter-spacing:.2px;white-space:nowrap} -@media (max-width: 767.98px){#navbar-logo::after{font-size:.95rem}} \ No newline at end of file +#navbar-home img{display:none!important} +#navbar-home{display:flex;align-items:center;gap:.5rem} +#navbar-home::after{content:"<%= @title %>";font-weight:600;font-size:1.05rem;line-height:1;color:inherit;letter-spacing:.2px;white-space:nowrap} +@media (max-width: 767.98px){#navbar-logo::after{font-size:.95rem}} diff --git a/config/templates/custom/templates/extra_links.tmpl.erb b/config/templates/custom/templates/extra_links.tmpl.erb index af78929..781e298 100644 --- a/config/templates/custom/templates/extra_links.tmpl.erb +++ b/config/templates/custom/templates/extra_links.tmpl.erb @@ -1,7 +1,9 @@ -{{svg "octicon-dot"}} +{{if .IsSigned}}{{svg "octicon-dot"}}{{end}} -