better docker/podman/etc isntall
60c9058 · gmorell · 2026-05-22 03:02
Files changed
modified
lib/git_gud_web/components/core_components.ex
+187
−6
@@ -590,7 +590,8 @@ defmodule GitGudWeb.CoreComponents do
| 590 | 590 | |
| 591 | 591 | @doc """ |
| 592 | 592 | Renders a tabbed block of `forgejo-runner register` + daemon command |
| 593 | − snippets for native binary, Docker, and Podman. | |
| 593 | + snippets for native binary, Docker, Podman, Podman Quadlet, and | |
| 594 | + Kubernetes. | |
| 594 | 595 | |
| 595 | 596 | Use on runner settings pages right after a new token is minted — |
| 596 | 597 | pass the bare token + the instance URL. |
@@ -614,13 +615,22 @@ defmodule GitGudWeb.CoreComponents do
| 614 | 615 | |> assign(:native_cmd, native_register_cmd(assigns)) |
| 615 | 616 | |> assign(:docker_cmd, docker_register_cmd(assigns)) |
| 616 | 617 | |> assign(:podman_cmd, podman_register_cmd(assigns)) |
| 618 | + |> assign(:quadlet_cmd, quadlet_register_cmd(assigns)) | |
| 619 | + |> assign(:k8s_cmd, kubernetes_register_cmd(assigns)) | |
| 617 | 620 | |
| 618 | 621 | ~H""" |
| 619 | 622 | <div role="tablist" class="tabs tabs-bordered"> |
| 620 | 623 | <input type="radio" name={@tabs_name} role="tab" class="tab" aria-label="Native" checked /> |
| 621 | 624 | <div role="tabpanel" class="tab-content p-3 space-y-2"> |
| 622 | 625 | <p class="text-xs opacity-70"> |
| 623 | − Run on a host with <code>forgejo-runner</code> on $PATH. | |
| 626 | + Run on a host with <code>forgejo-runner</code> on $PATH. See the | |
| 627 | + <a | |
| 628 | + class="link" | |
| 629 | + href="https://forgejo.org/docs/latest/admin/actions/installation/binary/" | |
| 630 | + target="_blank" | |
| 631 | + rel="noopener" | |
| 632 | + >binary install docs</a> | |
| 633 | + for the systemd unit. | |
| 624 | 634 | </p> |
| 625 | 635 | <pre class="text-xs bg-base-200 p-3 rounded overflow-x-auto" phx-no-curly-interpolation><%= @native_cmd %></pre> |
| 626 | 636 | </div> |
@@ -629,6 +639,13 @@ defmodule GitGudWeb.CoreComponents do
| 629 | 639 | <div role="tabpanel" class="tab-content p-3 space-y-2"> |
| 630 | 640 | <p class="text-xs opacity-70"> |
| 631 | 641 | Mounts the host's Docker socket so the runner can spawn job containers. |
| 642 | + For a dind-isolated <code>docker compose</code> variant, see the | |
| 643 | + <a | |
| 644 | + class="link" | |
| 645 | + href="https://forgejo.org/docs/latest/admin/actions/installation/docker/" | |
| 646 | + target="_blank" | |
| 647 | + rel="noopener" | |
| 648 | + >Docker install docs</a>. | |
| 632 | 649 | </p> |
| 633 | 650 | <pre class="text-xs bg-base-200 p-3 rounded overflow-x-auto" phx-no-curly-interpolation><%= @docker_cmd %></pre> |
| 634 | 651 | </div> |
@@ -637,10 +654,31 @@ defmodule GitGudWeb.CoreComponents do
| 637 | 654 | <div role="tabpanel" class="tab-content p-3 space-y-2"> |
| 638 | 655 | <p class="text-xs opacity-70"> |
| 639 | 656 | Rootless Podman. Enable user lingering (<code>loginctl enable-linger <user></code>) |
| 640 | − and ensure the Podman socket is reachable at <code>$XDG_RUNTIME_DIR/podman/podman.sock</code>. | |
| 657 | + and ensure the Podman socket is reachable at <code>$XDG_RUNTIME_DIR/podman/podman.sock</code> | |
| 658 | + (start it with <code>systemctl --user enable --now podman.socket</code>). | |
| 641 | 659 | </p> |
| 642 | 660 | <pre class="text-xs bg-base-200 p-3 rounded overflow-x-auto" phx-no-curly-interpolation><%= @podman_cmd %></pre> |
| 643 | 661 | </div> |
| 662 | + | |
| 663 | + <input type="radio" name={@tabs_name} role="tab" class="tab" aria-label="Quadlet" /> | |
| 664 | + <div role="tabpanel" class="tab-content p-3 space-y-2"> | |
| 665 | + <p class="text-xs opacity-70"> | |
| 666 | + Podman Quadlet (<code>systemd</code>-managed rootless container). | |
| 667 | + Drop the <code>.container</code> file in | |
| 668 | + <code>~/.config/containers/systemd/</code> and reload the user units. | |
| 669 | + </p> | |
| 670 | + <pre class="text-xs bg-base-200 p-3 rounded overflow-x-auto" phx-no-curly-interpolation><%= @quadlet_cmd %></pre> | |
| 671 | + </div> | |
| 672 | + | |
| 673 | + <input type="radio" name={@tabs_name} role="tab" class="tab" aria-label="Kubernetes" /> | |
| 674 | + <div role="tabpanel" class="tab-content p-3 space-y-2"> | |
| 675 | + <p class="text-xs opacity-70"> | |
| 676 | + Deployment + dind sidecar. The init container registers on first | |
| 677 | + start; the daemon then talks to <code>docker:dind</code> over | |
| 678 | + localhost. Apply with <code>kubectl apply -f forgejo-runner.yaml</code>. | |
| 679 | + </p> | |
| 680 | + <pre class="text-xs bg-base-200 p-3 rounded overflow-x-auto" phx-no-curly-interpolation><%= @k8s_cmd %></pre> | |
| 681 | + </div> | |
| 644 | 682 | </div> |
| 645 | 683 | """ |
| 646 | 684 | end |
@@ -648,13 +686,15 @@ defmodule GitGudWeb.CoreComponents do
| 648 | 686 | defp native_register_cmd(%{instance_url: url, token: token, runner_name: name}) do |
| 649 | 687 | Enum.join( |
| 650 | 688 | [ |
| 689 | + "forgejo-runner generate-config > runner-config.yml", | |
| 690 | + "", | |
| 651 | 691 | "forgejo-runner register \\", |
| 652 | 692 | " --instance #{url} \\", |
| 653 | 693 | " --token #{token} \\", |
| 654 | 694 | " --name #{name} \\", |
| 655 | 695 | " --no-interactive", |
| 656 | 696 | "", |
| 657 | − "forgejo-runner daemon" | |
| 697 | + "forgejo-runner daemon --config runner-config.yml" | |
| 658 | 698 | ], |
| 659 | 699 | "\n" |
| 660 | 700 | ) |
@@ -669,6 +709,9 @@ defmodule GitGudWeb.CoreComponents do
| 669 | 709 | [ |
| 670 | 710 | "mkdir -p ./runner-data && cd ./runner-data", |
| 671 | 711 | "", |
| 712 | + "docker run --rm #{image} \\", | |
| 713 | + " forgejo-runner generate-config > runner-config.yml", | |
| 714 | + "", | |
| 672 | 715 | "docker run --rm \\", |
| 673 | 716 | " --user $(id -u):$(id -g) \\", |
| 674 | 717 | " -v $(pwd):/data \\", |
@@ -685,7 +728,7 @@ defmodule GitGudWeb.CoreComponents do
| 685 | 728 | " -v $(pwd):/data \\", |
| 686 | 729 | " -v /var/run/docker.sock:/var/run/docker.sock \\", |
| 687 | 730 | " #{image} \\", |
| 688 | − " daemon" | |
| 731 | + " forgejo-runner daemon --config /data/runner-config.yml" | |
| 689 | 732 | ], |
| 690 | 733 | "\n" |
| 691 | 734 | ) |
@@ -700,6 +743,9 @@ defmodule GitGudWeb.CoreComponents do
| 700 | 743 | [ |
| 701 | 744 | "mkdir -p ./runner-data && cd ./runner-data", |
| 702 | 745 | "", |
| 746 | + "podman run --rm #{image} \\", | |
| 747 | + " forgejo-runner generate-config > runner-config.yml", | |
| 748 | + "", | |
| 703 | 749 | "podman run --rm \\", |
| 704 | 750 | " --userns=keep-id \\", |
| 705 | 751 | " --security-opt label=disable \\", |
@@ -718,7 +764,142 @@ defmodule GitGudWeb.CoreComponents do
| 718 | 764 | " -v $(pwd):/data \\", |
| 719 | 765 | " -v $XDG_RUNTIME_DIR/podman/podman.sock:/var/run/docker.sock \\", |
| 720 | 766 | " #{image} \\", |
| 721 | − " daemon" | |
| 767 | + " forgejo-runner daemon --config /data/runner-config.yml" | |
| 768 | + ], | |
| 769 | + "\n" | |
| 770 | + ) | |
| 771 | + end | |
| 772 | + | |
| 773 | + defp quadlet_register_cmd(%{instance_url: url, token: token, runner_name: name, image: image}) do | |
| 774 | + # Quadlets are read by `podman-system-generator` out of | |
| 775 | + # `~/.config/containers/systemd/` (rootless) and managed as user | |
| 776 | + # systemd units. The `Exec=` line maps to the container's CMD. | |
| 777 | + Enum.join( | |
| 778 | + [ | |
| 779 | + "# One-time bootstrap: generate config + register", | |
| 780 | + "mkdir -p ~/.local/share/forgejo-runner && cd ~/.local/share/forgejo-runner", | |
| 781 | + "", | |
| 782 | + "podman run --rm #{image} \\", | |
| 783 | + " forgejo-runner generate-config > runner-config.yml", | |
| 784 | + "", | |
| 785 | + "podman run --rm \\", | |
| 786 | + " --userns=keep-id \\", | |
| 787 | + " --security-opt label=disable \\", | |
| 788 | + " -v $(pwd):/data \\", | |
| 789 | + " #{image} \\", | |
| 790 | + " forgejo-runner register \\", | |
| 791 | + " --instance #{url} \\", | |
| 792 | + " --token #{token} \\", | |
| 793 | + " --name #{name} \\", | |
| 794 | + " --no-interactive", | |
| 795 | + "", | |
| 796 | + "# Drop this into ~/.config/containers/systemd/forgejo-runner.container", | |
| 797 | + "cat > ~/.config/containers/systemd/forgejo-runner.container <<'EOF'", | |
| 798 | + "[Unit]", | |
| 799 | + "Description=Forgejo Runner", | |
| 800 | + "After=network-online.target", | |
| 801 | + "Wants=network-online.target", | |
| 802 | + "", | |
| 803 | + "[Container]", | |
| 804 | + "Image=#{image}", | |
| 805 | + "ContainerName=forgejo-runner", | |
| 806 | + "UserNS=keep-id", | |
| 807 | + "SecurityLabelDisable=true", | |
| 808 | + "Volume=%h/.local/share/forgejo-runner:/data:Z", | |
| 809 | + "Volume=%t/podman/podman.sock:/var/run/docker.sock", | |
| 810 | + "Exec=forgejo-runner daemon --config /data/runner-config.yml", | |
| 811 | + "", | |
| 812 | + "[Service]", | |
| 813 | + "Restart=always", | |
| 814 | + "", | |
| 815 | + "[Install]", | |
| 816 | + "WantedBy=default.target", | |
| 817 | + "EOF", | |
| 818 | + "", | |
| 819 | + "systemctl --user daemon-reload", | |
| 820 | + "systemctl --user start forgejo-runner.service", | |
| 821 | + "loginctl enable-linger \"$USER\" # survive logout" | |
| 822 | + ], | |
| 823 | + "\n" | |
| 824 | + ) | |
| 825 | + end | |
| 826 | + | |
| 827 | + defp kubernetes_register_cmd(%{ | |
| 828 | + instance_url: url, | |
| 829 | + token: token, | |
| 830 | + runner_name: name, | |
| 831 | + image: image | |
| 832 | + }) do | |
| 833 | + # The init container performs `forgejo-runner register` against a | |
| 834 | + # shared emptyDir; the main container then starts the daemon and | |
| 835 | + # picks up `.runner` from that same volume. `docker:dind` runs as a | |
| 836 | + # sidecar so we don't expose the node's container runtime. | |
| 837 | + Enum.join( | |
| 838 | + [ | |
| 839 | + "# Save as forgejo-runner.yaml, then: kubectl apply -f forgejo-runner.yaml", | |
| 840 | + "apiVersion: v1", | |
| 841 | + "kind: Namespace", | |
| 842 | + "metadata:", | |
| 843 | + " name: forgejo-runner", | |
| 844 | + "---", | |
| 845 | + "apiVersion: v1", | |
| 846 | + "kind: Secret", | |
| 847 | + "metadata:", | |
| 848 | + " name: forgejo-runner-token", | |
| 849 | + " namespace: forgejo-runner", | |
| 850 | + "type: Opaque", | |
| 851 | + "stringData:", | |
| 852 | + " token: #{token}", | |
| 853 | + "---", | |
| 854 | + "apiVersion: apps/v1", | |
| 855 | + "kind: Deployment", | |
| 856 | + "metadata:", | |
| 857 | + " name: forgejo-runner", | |
| 858 | + " namespace: forgejo-runner", | |
| 859 | + "spec:", | |
| 860 | + " replicas: 1", | |
| 861 | + " selector:", | |
| 862 | + " matchLabels: { app: forgejo-runner }", | |
| 863 | + " template:", | |
| 864 | + " metadata:", | |
| 865 | + " labels: { app: forgejo-runner }", | |
| 866 | + " spec:", | |
| 867 | + " initContainers:", | |
| 868 | + " - name: register", | |
| 869 | + " image: #{image}", | |
| 870 | + " command: [\"sh\", \"-c\"]", | |
| 871 | + " args:", | |
| 872 | + " - |", | |
| 873 | + " set -e", | |
| 874 | + " cd /data", | |
| 875 | + " [ -f runner-config.yml ] || forgejo-runner generate-config > runner-config.yml", | |
| 876 | + " [ -f .runner ] || forgejo-runner register \\", | |
| 877 | + " --instance #{url} \\", | |
| 878 | + " --token \"$RUNNER_TOKEN\" \\", | |
| 879 | + " --name #{name} \\", | |
| 880 | + " --no-interactive", | |
| 881 | + " env:", | |
| 882 | + " - name: RUNNER_TOKEN", | |
| 883 | + " valueFrom:", | |
| 884 | + " secretKeyRef: { name: forgejo-runner-token, key: token }", | |
| 885 | + " volumeMounts:", | |
| 886 | + " - { name: data, mountPath: /data }", | |
| 887 | + " containers:", | |
| 888 | + " - name: runner", | |
| 889 | + " image: #{image}", | |
| 890 | + " command: [\"forgejo-runner\", \"daemon\", \"--config\", \"/data/runner-config.yml\"]", | |
| 891 | + " workingDir: /data", | |
| 892 | + " env:", | |
| 893 | + " - { name: DOCKER_HOST, value: \"tcp://localhost:2375\" }", | |
| 894 | + " volumeMounts:", | |
| 895 | + " - { name: data, mountPath: /data }", | |
| 896 | + " - name: dind", | |
| 897 | + " image: docker:dind", | |
| 898 | + " args: [\"dockerd\", \"-H\", \"tcp://0.0.0.0:2375\", \"--tls=false\"]", | |
| 899 | + " securityContext: { privileged: true }", | |
| 900 | + " volumes:", | |
| 901 | + " - name: data", | |
| 902 | + " emptyDir: {}" | |
| 722 | 903 | ], |
| 723 | 904 | "\n" |
| 724 | 905 | ) |
Parents: 5c83970