From 5a0579f03aaaed5d7bb8216a30c2573ea2dc0d8a Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Wed, 25 Sep 2024 09:46:06 -0700 Subject: [PATCH 01/18] basic entrypoint, automatic registration of runner works --- Dockerfile | 5 ++-- entrypoint.sh | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 50f1965..6843a3a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,10 +38,11 @@ LABEL maintainer="contact@forgejo.org" \ ENV HOME=/data -USER 1000:1000 +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh WORKDIR /data VOLUME ["/data"] -CMD ["/bin/forgejo-runner"] +ENTRYPOINT ["/entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..4fd5ae8 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +set -e + +## Initial setup +if [[ ! -d /data ]]; then + mkdir -p /data +fi +cd /data + +if [[ -z "${RUNNER_FILE}" ]]; then + RUNNER_FILE="/data/.runner" +fi + +if [[ ! -f "${RUNNER_FILE}" ]]; then + touch "${RUNNER_FILE}" +fi + +if [[ -z "${CONFIG_FILE}" ]]; then + CONFIG_FILE="/data/config.yml" +fi +CONFIG_ARG="--config ${CONFIG_FILE}" + +if [[ ! -f "${CONFIG_FILE}" ]]; then + forgejo-runner generate-config > ${CONFIG_FILE} +fi + +EXTRA_ARGS="" +if [[ ! -z "${RUNNER_LABELS}" ]]; then + EXTRA_ARGS="${EXTRA_ARGS} --labels ${RUNNER_LABELS}" +fi + +# For simplicity sake, I am not using the same ENV variable names as the original script + +if [[ -z "${RUNNER_FILE}" ]]; then + RUNNER_FILE=".runner" +fi +sed -i "/^ file:/c\ file: ${RUNNER_FILE}" ${CONFIG_FILE} + +if [[ ! -s "${RUNNER_FILE}" ]]; then + try=$((try + 1)) + success=0 + if [[ -z "${RUNNER_TOKEN}" ]]; then + echo "RUNNER_TOKEN is not set" + exit 1 + fi + + if [[ -z "${FORGEJO_URL}" ]]; then + echo "FORGEJO_URL is not set" + echo "Defaulting to http://forgejo:8080" + fi + + + # The point of this loop is to make it simple, when running both forgejo-runner and gitea in docker, + # for the forgejo-runner to wait a moment for gitea to become available before erroring out. Within + # the context of a single docker-compose, something similar could be done via healthchecks, but + # this is more flexible. + while [[ $success -eq 0 ]] && [[ $try -lt ${MAX_REG_ATTEMPTS:-10} ]]; do + forgejo-runner register \ + --instance "${FORGEJO_URL:-http://forgejo:8080}" \ + --token "${RUNNER_TOKEN}" \ + --name "${RUNNER_NAME:-$(hostname)}" \ + ${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log + + cat /tmp/reg.log | grep 'Runner registered successfully' >/dev/null + if [[ $? -eq 0 ]]; then + echo "SUCCESS" + success=1 + else + echo "Waiting to retry ..." + sleep 5 + fi + done +fi +# Prevent reading the token from the forgejo-runner process +unset RUNNER_TOKEN + +forgejo-runner daemon ${CONFIG_ARG} -- 2.45.2 From 190607cf35712c0e79b2385b240d9bdc3d194b33 Mon Sep 17 00:00:00 2001 From: Merith Date: Wed, 25 Sep 2024 13:00:54 -0700 Subject: [PATCH 02/18] address dockerfile feedback, further work on entrypoint --- Dockerfile | 3 +-- entrypoint.sh | 71 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6843a3a..c40304b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,8 +38,7 @@ LABEL maintainer="contact@forgejo.org" \ ENV HOME=/data -COPY entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh +COPY --chmod=555 entrypoint.sh /entrypoint.sh WORKDIR /data diff --git a/entrypoint.sh b/entrypoint.sh index 4fd5ae8..a11508c 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -8,36 +8,71 @@ if [[ ! -d /data ]]; then fi cd /data -if [[ -z "${RUNNER_FILE}" ]]; then - RUNNER_FILE="/data/.runner" -fi +RUNNER_USERID="${RUNNER_USERID:-1000}" -if [[ ! -f "${RUNNER_FILE}" ]]; then - touch "${RUNNER_FILE}" +## Setup User +if id "forgejo-runner" &>/dev/null; then + if [[ ! -z "${RUNNER_USERID}" ]]; then + echo "Changing UID of forgejo-runner to ${RUNNER_USERID}" + sed -i "s/^forgejo-runner:[^:]*:[^:]*:/forgejo-runner:x:${RUNNER_USERID}:/" /etc/passwd + fi +else + echo "Creating user forgejo-runner with UID ${RUNNER_USERID}" + adduser --uid "${RUNNER_USERID}" --home /home/forgejo-runner --disabled-password --gecos "" forgejo-runner fi +chown -R forgejo-runner:forgejo-runner /data +## Handle and alter the config file if [[ -z "${CONFIG_FILE}" ]]; then CONFIG_FILE="/data/config.yml" fi CONFIG_ARG="--config ${CONFIG_FILE}" +DOCKER_HOST=${DOCKER_HOST:-docker} +echo "DOCKER_HOST: ${DOCKER_HOST}" if [[ ! -f "${CONFIG_FILE}" ]]; then - forgejo-runner generate-config > ${CONFIG_FILE} + su -c "forgejo-runner generate-config > ${CONFIG_FILE}" forgejo-runner + + # Remove test environment variables if they exist in the config file + sed -i "/^ A_TEST_ENV_NAME_1:/d" ${CONFIG_FILE} + sed -i "/^ A_TEST_ENV_NAME_2:/d" ${CONFIG_FILE} + + # apply default values for docker + sed -i "/\"labels\":/c\ \"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} + + sed -i "/^ network:/c\ network: host" config.yml + sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} + sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" config.yml + sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2376" ${CONFIG_FILE} fi +if [[ ! -z "${ENV_FILE}" ]]; then + sed -i "/^ env_file:/c\ env_file: ${ENV_FILE}" ${CONFIG_FILE} +else + ENV_FILE="/data/.env" +fi +if [[ ! -f "${ENV_FILE}" ]]; then + echo "Creating ${ENV_FILE} and populating with default values" + cat < ${ENV_FILE} + DOCKER_TLS_VERIFY: 1 + DOCKER_CERT_PATH: /certs/client +EOF +fi + + EXTRA_ARGS="" if [[ ! -z "${RUNNER_LABELS}" ]]; then EXTRA_ARGS="${EXTRA_ARGS} --labels ${RUNNER_LABELS}" fi -# For simplicity sake, I am not using the same ENV variable names as the original script - +# Set the runner file if [[ -z "${RUNNER_FILE}" ]]; then - RUNNER_FILE=".runner" + RUNNER_FILE=".runner.json" # use json so editors know how to highlight fi sed -i "/^ file:/c\ file: ${RUNNER_FILE}" ${CONFIG_FILE} if [[ ! -s "${RUNNER_FILE}" ]]; then + touch ${RUNNER_FILE} try=$((try + 1)) success=0 if [[ -z "${RUNNER_TOKEN}" ]]; then @@ -45,22 +80,16 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then exit 1 fi - if [[ -z "${FORGEJO_URL}" ]]; then - echo "FORGEJO_URL is not set" - echo "Defaulting to http://forgejo:8080" - fi - - # The point of this loop is to make it simple, when running both forgejo-runner and gitea in docker, # for the forgejo-runner to wait a moment for gitea to become available before erroring out. Within # the context of a single docker-compose, something similar could be done via healthchecks, but # this is more flexible. while [[ $success -eq 0 ]] && [[ $try -lt ${MAX_REG_ATTEMPTS:-10} ]]; do - forgejo-runner register \ - --instance "${FORGEJO_URL:-http://forgejo:8080}" \ - --token "${RUNNER_TOKEN}" \ - --name "${RUNNER_NAME:-$(hostname)}" \ - ${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log + su -c "forgejo-runner register \ + --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ + --token \"${RUNNER_TOKEN}\" \ + --name \"${RUNNER_NAME:-$(hostname)}\" \ + ${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log" forgejo-runner cat /tmp/reg.log | grep 'Runner registered successfully' >/dev/null if [[ $? -eq 0 ]]; then @@ -75,4 +104,4 @@ fi # Prevent reading the token from the forgejo-runner process unset RUNNER_TOKEN -forgejo-runner daemon ${CONFIG_ARG} +su -c "forgejo-runner daemon ${CONFIG_ARG}" forgejo-runner -- 2.45.2 From 16e18662a01078a90a4ad77c642ad4de2e21d087 Mon Sep 17 00:00:00 2001 From: Merith Date: Wed, 25 Sep 2024 13:34:18 -0700 Subject: [PATCH 03/18] add a root-user check, clean up some formatting --- entrypoint.sh | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index a11508c..bed8152 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,7 +2,13 @@ set -e -## Initial setup +# Check if the script is run as root +if [ "$EUID" -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + +# Initial setup if [[ ! -d /data ]]; then mkdir -p /data fi @@ -10,7 +16,7 @@ cd /data RUNNER_USERID="${RUNNER_USERID:-1000}" -## Setup User +# Setup User if id "forgejo-runner" &>/dev/null; then if [[ ! -z "${RUNNER_USERID}" ]]; then echo "Changing UID of forgejo-runner to ${RUNNER_USERID}" @@ -20,9 +26,11 @@ else echo "Creating user forgejo-runner with UID ${RUNNER_USERID}" adduser --uid "${RUNNER_USERID}" --home /home/forgejo-runner --disabled-password --gecos "" forgejo-runner fi + +# Ensure /data is owned by the runner user chown -R forgejo-runner:forgejo-runner /data -## Handle and alter the config file +# Handle and alter the config file if [[ -z "${CONFIG_FILE}" ]]; then CONFIG_FILE="/data/config.yml" fi @@ -37,12 +45,12 @@ if [[ ! -f "${CONFIG_FILE}" ]]; then sed -i "/^ A_TEST_ENV_NAME_1:/d" ${CONFIG_FILE} sed -i "/^ A_TEST_ENV_NAME_2:/d" ${CONFIG_FILE} - # apply default values for docker + # Apply default values for docker sed -i "/\"labels\":/c\ \"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} - sed -i "/^ network:/c\ network: host" config.yml + sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} - sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" config.yml + sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" ${CONFIG_FILE} sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2376" ${CONFIG_FILE} fi @@ -51,6 +59,7 @@ if [[ ! -z "${ENV_FILE}" ]]; then else ENV_FILE="/data/.env" fi + if [[ ! -f "${ENV_FILE}" ]]; then echo "Creating ${ENV_FILE} and populating with default values" cat < ${ENV_FILE} @@ -59,7 +68,6 @@ if [[ ! -f "${ENV_FILE}" ]]; then EOF fi - EXTRA_ARGS="" if [[ ! -z "${RUNNER_LABELS}" ]]; then EXTRA_ARGS="${EXTRA_ARGS} --labels ${RUNNER_LABELS}" @@ -101,6 +109,7 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then fi done fi + # Prevent reading the token from the forgejo-runner process unset RUNNER_TOKEN -- 2.45.2 From 3c5ba1c1d2416d201d0e4d7a35fb101778f0be35 Mon Sep 17 00:00:00 2001 From: Merith Date: Wed, 25 Sep 2024 14:05:56 -0700 Subject: [PATCH 04/18] push example docker-compose for runner and forgejo --- entrypoint.sh | 1 + examples/docker-compose/.gitignore | 2 + .../compose-forgejo-and-runner.yml | 89 +++++++------------ 3 files changed, 36 insertions(+), 56 deletions(-) create mode 100644 examples/docker-compose/.gitignore diff --git a/entrypoint.sh b/entrypoint.sh index bed8152..c19b9cd 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -51,6 +51,7 @@ if [[ ! -f "${CONFIG_FILE}" ]]; then sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" ${CONFIG_FILE} + sed -i "/^ valid_volumes:/c\ valid_volumes:\n - /certs/client" ${CONFIG_FILE} sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2376" ${CONFIG_FILE} fi diff --git a/examples/docker-compose/.gitignore b/examples/docker-compose/.gitignore new file mode 100644 index 0000000..294fcad --- /dev/null +++ b/examples/docker-compose/.gitignore @@ -0,0 +1,2 @@ +forgejo/ +forgejo-runner/ diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index 4794985..c15c63d 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -11,18 +11,23 @@ # NOTE: a token obtained from the Forgejo web interface cannot be used # as a shared secret. # -# Replace {ROOT_PASSWORD} with a secure password +# Replace {RUNNER_TOKEN} with the token obtained from the Forgejo web interface. # +networks: + forgejo: + volumes: docker_certs: services: - docker-in-docker: image: code.forgejo.org/oci/docker:dind + container_name: docker # needed for docker internal DNS resolution hostname: docker # Must set hostname as TLS certificates are only valid for docker or localhost privileged: true + networks: + - forgejo environment: DOCKER_TLS_CERTDIR: /certs DOCKER_HOST: docker-in-docker @@ -31,63 +36,35 @@ services: forgejo: image: codeberg.org/forgejo/forgejo:1.21 - command: >- - bash -c ' - /bin/s6-svscan /etc/s6 & - sleep 10 ; - su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET}" git ; - su -c "forgejo admin user create --admin --username root --password {ROOT_PASSWORD} --email root@example.com" git ; - sleep infinity - ' - environment: - FORGEJO__security__INSTALL_LOCK: "true" - FORGEJO__log__LEVEL: "debug" - FORGEJO__repository__ENABLE_PUSH_CREATE_USER: "true" - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE: "false" - FORGEJO__repository__DEFAULT_REPO_UNITS: "repo.code,repo.actions" + container_name: forgejo + networks: + - forgejo volumes: - - /srv/forgejo-data:/data + - ./forgejo:/data ports: - 8080:3000 - runner-register: - image: code.forgejo.org/forgejo/runner:3.4.1 - links: - - docker-in-docker - - forgejo - environment: - DOCKER_HOST: tcp://docker-in-docker:2376 + forgejo-runner: + ## TODO: Update image to the the release + ## made from this PR: https://code.forgejo.org/forgejo/runner/pulls/283 + + # image: code.forgejo.org/forgejo/runner:3.4.1 + build: ../../ + container_name: forgejo-runner volumes: - - /srv/runner-data:/data - user: 0:0 - command: >- - bash -ec ' - while : ; do - forgejo-runner create-runner-file --connect --instance http://forgejo:3000 --name runner --secret {SHARED_SECRET} && break ; - sleep 1 ; - done ; - sed -i -e "s|\"labels\": null|\"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]|" .runner ; - forgejo-runner generate-config > config.yml ; - sed -i -e "s|network: .*|network: host|" config.yml ; - sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://docker:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ; - sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ; - sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml ; - chown -R 1000:1000 /data - ' - - runner-daemon: - image: code.forgejo.org/forgejo/runner:3.4.1 - links: - - docker-in-docker - - forgejo - environment: - DOCKER_HOST: tcp://docker:2376 - DOCKER_CERT_PATH: /certs/client - DOCKER_TLS_VERIFY: "1" - volumes: - - /srv/runner-data:/data + - ./forgejo-runner:/data - docker_certs:/certs - command: >- - bash -c ' - while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done - ' + networks: + - forgejo + depends_on: + - docker-in-docker + - forgejo + environment: + CONFIG_FILE: config.yml # defaults to /data/config.yml + + FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 + + RUNNER_FILE: runner.json # defaults to /data/runner.json + RUNNER_NAME: forgejo-runner # defaults to forgejo-runner, used for registration + RUNNER_TOKEN: "{RUNNER_TOKEN}" + RUNNER_USER: 1000 # defaults to 1000 -- 2.45.2 From c1654806c5f2e3223df68c6fa6a53a6f49c6bdb4 Mon Sep 17 00:00:00 2001 From: Merith Date: Wed, 25 Sep 2024 15:21:53 -0700 Subject: [PATCH 05/18] update entrypoint and dockerfile, fix test workflow update dockerfile, rework entrypoint execution, update compose and test --- .forgejo/workflows/example-docker-compose.yml | 11 ++- Dockerfile | 2 +- Dockerfile.rootless | 6 ++ entrypoint.sh | 89 ++++++++++++------- .../compose-forgejo-and-runner.yml | 44 ++++++++- 5 files changed, 112 insertions(+), 40 deletions(-) create mode 100644 Dockerfile.rootless diff --git a/.forgejo/workflows/example-docker-compose.yml b/.forgejo/workflows/example-docker-compose.yml index 4e2f547..2a18988 100644 --- a/.forgejo/workflows/example-docker-compose.yml +++ b/.forgejo/workflows/example-docker-compose.yml @@ -39,8 +39,11 @@ jobs: # Launch Forgejo & the runner # $cli up -d - for delay in $(seq 60) ; do test -f /srv/runner-data/.runner && break ; sleep 30 ; done - test -f /srv/runner-data/.runner + for delay in $(seq 60) ; do + test -f ./forgejo-runner/runner.json && break + sleep 30 + done + test -f ./forgejo-runner/runner.json # # Run the demo workflow # @@ -56,11 +59,11 @@ jobs: grep --quiet "$success" /tmp/out && break grep --quiet "$failure" /tmp/out && break $cli ps --all - $cli logs --tail=20 runner-daemon demo-workflow + $cli logs --tail=20 forgejo-runner demo-workflow sleep 30 done grep --quiet "$success" /tmp/out - $cli logs runner-daemon > /tmp/runner.log + $cli logs forgejo-runner > /tmp/runner.log grep --quiet 'Start image=code.forgejo.org/oci/node:20-bookworm' /tmp/runner.log - name: full docker compose logs diff --git a/Dockerfile b/Dockerfile index c40304b..ed94063 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/tonistiigi/xx AS xx -FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.21-alpine3.19 as build-env +FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.21-alpine3.19 AS build-env # # Transparently cross compile for the target platform diff --git a/Dockerfile.rootless b/Dockerfile.rootless new file mode 100644 index 0000000..882be5c --- /dev/null +++ b/Dockerfile.rootless @@ -0,0 +1,6 @@ +FROM code.forgejo.org/forgejo/runner:3.4.1 + +USER 1000:1000 +## In Theory these can be removed on next release of the runner image +COPY --chown=forgejo-runner:forgejo-runner --chmod=555 ./entrypoint.sh /entrypoint +ENTRYPOINT [ "/entrypoint" ] \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh index c19b9cd..c6145e9 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,11 +2,15 @@ set -e -# Check if the script is run as root -if [ "$EUID" -ne 0 ]; then - echo "This script must be run as root" - exit 1 -fi +run_command() { + local cmd="$1" + echo "Running $cmd as $(id -u)" + if [[ "$ISROOT" == true ]]; then + su -c "$cmd" forgejo-runner + else + eval "$cmd" + fi +} # Initial setup if [[ ! -d /data ]]; then @@ -16,38 +20,48 @@ cd /data RUNNER_USERID="${RUNNER_USERID:-1000}" -# Setup User -if id "forgejo-runner" &>/dev/null; then - if [[ ! -z "${RUNNER_USERID}" ]]; then - echo "Changing UID of forgejo-runner to ${RUNNER_USERID}" - sed -i "s/^forgejo-runner:[^:]*:[^:]*:/forgejo-runner:x:${RUNNER_USERID}:/" /etc/passwd - fi -else - echo "Creating user forgejo-runner with UID ${RUNNER_USERID}" - adduser --uid "${RUNNER_USERID}" --home /home/forgejo-runner --disabled-password --gecos "" forgejo-runner +# Check if the script is running as root +if [[ $(id -u) -eq 0 ]]; then + ISROOT=true fi -# Ensure /data is owned by the runner user -chown -R forgejo-runner:forgejo-runner /data +if [[ "$ISROOT" == true ]]; then + # Check if the forgejo-runner user exists + if id "forgejo-runner" &>/dev/null; then + echo "forgejo-runner user exists." + + # Change the user ID if needed + CURRENT_UID=$(id -u forgejo-runner) + if [[ "${CURRENT_UID}" -ne "${RUNNER_USERID}" ]]; then + echo "Changing UID of forgejo-runner to ${RUNNER_USERID}" + sed -i "s/^forgejo-runner:[^:]*:[^:]*:/forgejo-runner:x:${RUNNER_USERID}:/" /etc/passwd + fi + else + echo "Creating user forgejo-runner with UID ${RUNNER_USERID}" + adduser --uid "${RUNNER_USERID}" --home /home/forgejo-runner --disabled-password --gecos "" forgejo-runner + fi + + # Ensure /data is owned by the runner user + chown -R forgejo-runner:forgejo-runner /data +fi # Handle and alter the config file if [[ -z "${CONFIG_FILE}" ]]; then + echo "CONFIG_FILE is not set" CONFIG_FILE="/data/config.yml" fi CONFIG_ARG="--config ${CONFIG_FILE}" DOCKER_HOST=${DOCKER_HOST:-docker} -echo "DOCKER_HOST: ${DOCKER_HOST}" if [[ ! -f "${CONFIG_FILE}" ]]; then - su -c "forgejo-runner generate-config > ${CONFIG_FILE}" forgejo-runner + run_command "forgejo-runner generate-config > ${CONFIG_FILE}" forgejo-runner # Remove test environment variables if they exist in the config file sed -i "/^ A_TEST_ENV_NAME_1:/d" ${CONFIG_FILE} sed -i "/^ A_TEST_ENV_NAME_2:/d" ${CONFIG_FILE} # Apply default values for docker - sed -i "/\"labels\":/c\ \"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} - + sed -i "/^ labels:/c\ \"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" ${CONFIG_FILE} @@ -63,7 +77,7 @@ fi if [[ ! -f "${ENV_FILE}" ]]; then echo "Creating ${ENV_FILE} and populating with default values" - cat < ${ENV_FILE} + cat <${ENV_FILE} DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: /certs/client EOF @@ -76,7 +90,7 @@ fi # Set the runner file if [[ -z "${RUNNER_FILE}" ]]; then - RUNNER_FILE=".runner.json" # use json so editors know how to highlight + RUNNER_FILE=".runner.json" # use json so editors know how to highlight fi sed -i "/^ file:/c\ file: ${RUNNER_FILE}" ${CONFIG_FILE} @@ -84,9 +98,15 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then touch ${RUNNER_FILE} try=$((try + 1)) success=0 - if [[ -z "${RUNNER_TOKEN}" ]]; then - echo "RUNNER_TOKEN is not set" - exit 1 + + if [[ ! -z "${FORGEJO_SECRET}" ]]; then + EXTRA_ARGS="${EXTRA_ARGS} --secret ${FORGEJO_SECRET}" + else + if [[ -z "${RUNNER_TOKEN}" ]]; then + echo "RUNNER_TOKEN is not set" + exit 1 + fi + EXTRA_ARGS="${EXTRA_ARGS} --token ${RUNNER_TOKEN}" fi # The point of this loop is to make it simple, when running both forgejo-runner and gitea in docker, @@ -94,13 +114,18 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then # the context of a single docker-compose, something similar could be done via healthchecks, but # this is more flexible. while [[ $success -eq 0 ]] && [[ $try -lt ${MAX_REG_ATTEMPTS:-10} ]]; do - su -c "forgejo-runner register \ - --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ - --token \"${RUNNER_TOKEN}\" \ - --name \"${RUNNER_NAME:-$(hostname)}\" \ - ${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log" forgejo-runner + # run_command "forgejo-runner register \ + # --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ + # --name \"${RUNNER_NAME:-$(hostname)}\" \ + # ${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log" - cat /tmp/reg.log | grep 'Runner registered successfully' >/dev/null + run_command "forgejo-runner create-runner-file --connect \ + --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ + --name \"${RUNNER_NAME:-$(hostname)}\" \ + ${CONFIG_ARG} ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" + + + cat /tmp/reg.log | grep 'connection successful' >/dev/null if [[ $? -eq 0 ]]; then echo "SUCCESS" success=1 @@ -114,4 +139,4 @@ fi # Prevent reading the token from the forgejo-runner process unset RUNNER_TOKEN -su -c "forgejo-runner daemon ${CONFIG_ARG}" forgejo-runner +run_command "forgejo-runner daemon ${CONFIG_ARG}" diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index c15c63d..eb6006e 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -11,7 +11,7 @@ # NOTE: a token obtained from the Forgejo web interface cannot be used # as a shared secret. # -# Replace {RUNNER_TOKEN} with the token obtained from the Forgejo web interface. +# Replace ${RUNNER_TOKEN} with the token obtained from the Forgejo web interface. # networks: @@ -43,14 +43,24 @@ services: - ./forgejo:/data ports: - 8080:3000 + command: >- + bash -c ' + /bin/s6-svscan /etc/s6 & + sleep 10 ; + su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET}" git ; + sleep infinity + ' forgejo-runner: ## TODO: Update image to the the release ## made from this PR: https://code.forgejo.org/forgejo/runner/pulls/283 # image: code.forgejo.org/forgejo/runner:3.4.1 - build: ../../ + build: + context: ../../ + dockerfile: Dockerfile container_name: forgejo-runner + # user: "1000" # set to run rootless, overrides RUNNER_USER volumes: - ./forgejo-runner:/data - docker_certs:/certs @@ -63,8 +73,36 @@ services: CONFIG_FILE: config.yml # defaults to /data/config.yml FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 + FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's RUNNER_FILE: runner.json # defaults to /data/runner.json RUNNER_NAME: forgejo-runner # defaults to forgejo-runner, used for registration - RUNNER_TOKEN: "{RUNNER_TOKEN}" + RUNNER_TOKEN: "${RUNNER_TOKEN}" RUNNER_USER: 1000 # defaults to 1000 + + forgejo-runner-rootless: + ## TODO: Update image to the the release + ## made from this PR: https://code.forgejo.org/forgejo/runner/pulls/283 + + # image: code.forgejo.org/forgejo/runner:3.4.1 + build: + context: ../../ + dockerfile: Dockerfile.rootless + container_name: forgejo-runner-rootless + volumes: + - ./forgejo-runner:/data + - docker_certs:/certs + networks: + - forgejo + depends_on: + - docker-in-docker + - forgejo + environment: + CONFIG_FILE: config-rootless.yml # defaults to /data/config.yml + + FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 + FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's + + RUNNER_FILE: runner-rootless.json # defaults to /data/runner.json + RUNNER_NAME: forgejo-runner # defaults to forgejo-runner, used for registration + RUNNER_TOKEN: "${RUNNER_TOKEN}" \ No newline at end of file -- 2.45.2 From 1e6e1cb3c2c4e8fa9bd39754cd70cb756d59548c Mon Sep 17 00:00:00 2001 From: Merith Date: Wed, 25 Sep 2024 17:10:50 -0700 Subject: [PATCH 06/18] disabled TLS in example, not needed for a closed docker network --- entrypoint.sh | 26 +++++++++---------- .../compose-forgejo-and-runner.yml | 6 ++--- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index c6145e9..d1376c0 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -64,9 +64,14 @@ if [[ ! -f "${CONFIG_FILE}" ]]; then sed -i "/^ labels:/c\ \"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} - sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" ${CONFIG_FILE} - sed -i "/^ valid_volumes:/c\ valid_volumes:\n - /certs/client" ${CONFIG_FILE} - sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2376" ${CONFIG_FILE} + + if [[ "${DOCKER_TLS_VERIFY}" -ne 1 ]]; then + sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2375" ${CONFIG_FILE} + else + sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2376" ${CONFIG_FILE} + sed -i "/^ valid_volumes:/c\ valid_volumes:\n - /certs/client" ${CONFIG_FILE} + sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" ${CONFIG_FILE} + fi fi if [[ ! -z "${ENV_FILE}" ]]; then @@ -76,11 +81,8 @@ else fi if [[ ! -f "${ENV_FILE}" ]]; then - echo "Creating ${ENV_FILE} and populating with default values" - cat <${ENV_FILE} - DOCKER_TLS_VERIFY: 1 - DOCKER_CERT_PATH: /certs/client -EOF + echo "Creating ${ENV_FILE}" + touch ${ENV_FILE} fi EXTRA_ARGS="" @@ -101,12 +103,14 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then if [[ ! -z "${FORGEJO_SECRET}" ]]; then EXTRA_ARGS="${EXTRA_ARGS} --secret ${FORGEJO_SECRET}" + echo "Registering with SECRET" else if [[ -z "${RUNNER_TOKEN}" ]]; then echo "RUNNER_TOKEN is not set" exit 1 fi EXTRA_ARGS="${EXTRA_ARGS} --token ${RUNNER_TOKEN}" + echo "Registering with TOKEN" fi # The point of this loop is to make it simple, when running both forgejo-runner and gitea in docker, @@ -114,17 +118,11 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then # the context of a single docker-compose, something similar could be done via healthchecks, but # this is more flexible. while [[ $success -eq 0 ]] && [[ $try -lt ${MAX_REG_ATTEMPTS:-10} ]]; do - # run_command "forgejo-runner register \ - # --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ - # --name \"${RUNNER_NAME:-$(hostname)}\" \ - # ${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log" - run_command "forgejo-runner create-runner-file --connect \ --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ --name \"${RUNNER_NAME:-$(hostname)}\" \ ${CONFIG_ARG} ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" - cat /tmp/reg.log | grep 'connection successful' >/dev/null if [[ $? -eq 0 ]]; then echo "SUCCESS" diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index eb6006e..e38e841 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -7,7 +7,7 @@ # openssl rand -hex 20 # # Replace all occurences of {SHARED_SECRET} below with the output. -# +# # NOTE: a token obtained from the Forgejo web interface cannot be used # as a shared secret. # @@ -29,7 +29,7 @@ services: networks: - forgejo environment: - DOCKER_TLS_CERTDIR: /certs + DOCKER_TLS_CERTDIR: "" # set to "certs" to use the TLS certificates, also update existing runner configs to use port 2376 DOCKER_HOST: docker-in-docker volumes: - docker_certs:/certs @@ -104,5 +104,5 @@ services: FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's RUNNER_FILE: runner-rootless.json # defaults to /data/runner.json - RUNNER_NAME: forgejo-runner # defaults to forgejo-runner, used for registration + RUNNER_NAME: forgejo-runner-rootless # defaults to forgejo-runner, used for registration RUNNER_TOKEN: "${RUNNER_TOKEN}" \ No newline at end of file -- 2.45.2 From 2c4a1d43beeb359eee0c40366cb90907f4760a52 Mon Sep 17 00:00:00 2001 From: Merith Date: Thu, 26 Sep 2024 07:28:00 -0700 Subject: [PATCH 07/18] revert changes to workflow --- .forgejo/workflows/example-docker-compose.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.forgejo/workflows/example-docker-compose.yml b/.forgejo/workflows/example-docker-compose.yml index 2a18988..f1089ec 100644 --- a/.forgejo/workflows/example-docker-compose.yml +++ b/.forgejo/workflows/example-docker-compose.yml @@ -39,11 +39,8 @@ jobs: # Launch Forgejo & the runner # $cli up -d - for delay in $(seq 60) ; do - test -f ./forgejo-runner/runner.json && break - sleep 30 - done - test -f ./forgejo-runner/runner.json + for delay in $(seq 60) ; do test -f /srv/runner-data/.runner && break ; sleep 30 ; done + test -f /srv/runner-data/.runner # # Run the demo workflow # @@ -59,15 +56,15 @@ jobs: grep --quiet "$success" /tmp/out && break grep --quiet "$failure" /tmp/out && break $cli ps --all - $cli logs --tail=20 forgejo-runner demo-workflow + $cli logs --tail=20 runner-daemon demo-workflow sleep 30 done grep --quiet "$success" /tmp/out - $cli logs forgejo-runner > /tmp/runner.log + $cli logs runner-daemon > /tmp/runner.log grep --quiet 'Start image=code.forgejo.org/oci/node:20-bookworm' /tmp/runner.log - name: full docker compose logs if: always() run: | cd examples/docker-compose - docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml logs + docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml logs \ No newline at end of file -- 2.45.2 From ea96696f10c9c700bb14b093821917ba4dd6a2e6 Mon Sep 17 00:00:00 2001 From: Merith Date: Thu, 26 Sep 2024 15:08:31 -0700 Subject: [PATCH 08/18] remove rootless dockerfile, updatedate entrypoint, update docker compose Removed the rootless dockerfile as upon further investigation into how a `rootless` container works, the entrypoint that has been written fully accomodates that to reflect this the compose file has had the rootless config removed from it as it is no longer needed to test a seperate container image, added a debug echo function `decho` to the entrypoint, when `DEBUG=true` it will print "[entrypoint] message content" added a 10 second wait to the entrypoint to allow other services such as docker-in-docker and forgejo to finish launching before the runner is launched, this is bypassable by `SKIP_WAIT=true` applied several modifications requested by viceice, --- Dockerfile.rootless | 6 -- entrypoint.sh | 73 ++++++++++++++----- .../compose-forgejo-and-runner.yml | 70 +++++++----------- 3 files changed, 78 insertions(+), 71 deletions(-) delete mode 100644 Dockerfile.rootless diff --git a/Dockerfile.rootless b/Dockerfile.rootless deleted file mode 100644 index 882be5c..0000000 --- a/Dockerfile.rootless +++ /dev/null @@ -1,6 +0,0 @@ -FROM code.forgejo.org/forgejo/runner:3.4.1 - -USER 1000:1000 -## In Theory these can be removed on next release of the runner image -COPY --chown=forgejo-runner:forgejo-runner --chmod=555 ./entrypoint.sh /entrypoint -ENTRYPOINT [ "/entrypoint" ] \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh index d1376c0..ed17b19 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,25 +4,32 @@ set -e run_command() { local cmd="$1" - echo "Running $cmd as $(id -u)" + redacted_cmd=$(echo "$cmd" | sed -E 's/(--secret\s+|--token\s+)[^ ]+/--\1[REDACTED]/g') + decho "Running command: $redacted_cmd" if [[ "$ISROOT" == true ]]; then + decho "Running as forgejo-runner" su -c "$cmd" forgejo-runner else + decho "Running as RUNNER_USER: ${RUNNER_USER}" eval "$cmd" fi } +decho() { + if [[ "${DEBUG}" == "true" ]]; then + echo "[entrypoint] $@" + fi +} + # Initial setup -if [[ ! -d /data ]]; then - mkdir -p /data -fi cd /data -RUNNER_USERID="${RUNNER_USERID:-1000}" - +decho "RUNNER_USER: ${RUNNER_USER}" +RUNNER_USER="${RUNNER_USER:-1000}" # Check if the script is running as root if [[ $(id -u) -eq 0 ]]; then ISROOT=true + decho "Running as root" fi if [[ "$ISROOT" == true ]]; then @@ -32,17 +39,21 @@ if [[ "$ISROOT" == true ]]; then # Change the user ID if needed CURRENT_UID=$(id -u forgejo-runner) - if [[ "${CURRENT_UID}" -ne "${RUNNER_USERID}" ]]; then - echo "Changing UID of forgejo-runner to ${RUNNER_USERID}" - sed -i "s/^forgejo-runner:[^:]*:[^:]*:/forgejo-runner:x:${RUNNER_USERID}:/" /etc/passwd + decho "CURRENT_UID: ${CURRENT_UID}" + if [[ "${CURRENT_UID}" -ne "${RUNNER_USER}" ]]; then + echo "Changing UID of forgejo-runner to ${RUNNER_USER}" + sed -i "s/^forgejo-runner:[^:]*:[^:]*:/forgejo-runner:x:${RUNNER_USER}:/" /etc/passwd fi else - echo "Creating user forgejo-runner with UID ${RUNNER_USERID}" - adduser --uid "${RUNNER_USERID}" --home /home/forgejo-runner --disabled-password --gecos "" forgejo-runner + echo "Creating user forgejo-runner with UID ${RUNNER_USER}" + adduser --uid "${RUNNER_USER}" --home /home/forgejo-runner --disabled-password --gecos "" forgejo-runner fi # Ensure /data is owned by the runner user - chown -R forgejo-runner:forgejo-runner /data + if [[ $(stat -c "%u" /data) != "${RUNNER_USER}" ]]; then + decho "Changing ownership of /data to ${RUNNER_USER}" + chown -R forgejo-runner:forgejo-runner /data + fi fi # Handle and alter the config file @@ -51,9 +62,16 @@ if [[ -z "${CONFIG_FILE}" ]]; then CONFIG_FILE="/data/config.yml" fi CONFIG_ARG="--config ${CONFIG_FILE}" +decho "CONFIG: ${CONFIG_ARG}" DOCKER_HOST=${DOCKER_HOST:-docker} +DOCKER_TLS_CERTDIR=${DOCKER_TLS_CERTDIR:-"/certs/client"} +DOCKER_TLS_VERIFY=${DOCKER_TLS_VERIFY:-0} +decho "DOCKER_HOST: ${DOCKER_HOST}" +decho "DOCKER_TLS_CERTDIR: ${DOCKER_TLS_CERTDIR}" +decho "DOCKER_TLS_VERIFY: ${DOCKER_TLS_VERIFY}" if [[ ! -f "${CONFIG_FILE}" ]]; then + echo "Creating ${CONFIG_FILE}" run_command "forgejo-runner generate-config > ${CONFIG_FILE}" forgejo-runner # Remove test environment variables if they exist in the config file @@ -65,41 +83,53 @@ if [[ ! -f "${CONFIG_FILE}" ]]; then sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} + if [[ "${DOCKER_TLS_VERIFY}" -ne 1 ]]; then + decho "Docker TLS diabled" sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2375" ${CONFIG_FILE} else + decho "Docker TLS enabled" sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2376" ${CONFIG_FILE} - sed -i "/^ valid_volumes:/c\ valid_volumes:\n - /certs/client" ${CONFIG_FILE} - sed -i "/^ options:/c\ options: -v /certs/client:/certs/client" ${CONFIG_FILE} + sed -i "/^ valid_volumes:/c\ valid_volumes:\n - ${DOCKER_TLS_CERTDIR}" ${CONFIG_FILE} + sed -i "/^ options:/c\ options: -v ${DOCKER_TLS_CERTDIR}:${DOCKER_TLS_CERTDIR}" ${CONFIG_FILE} fi fi -if [[ ! -z "${ENV_FILE}" ]]; then - sed -i "/^ env_file:/c\ env_file: ${ENV_FILE}" ${CONFIG_FILE} -else - ENV_FILE="/data/.env" -fi +ENV_FILE=${ENV_FILE:-"/data/.env"} +decho "ENV_FILE: ${ENV_FILE}" +sed -i "/^ env_file:/c\ env_file: ${ENV_FILE}" ${CONFIG_FILE} if [[ ! -f "${ENV_FILE}" ]]; then echo "Creating ${ENV_FILE}" touch ${ENV_FILE} + echo "DOCKER_HOST=${DOCKER_HOST}" >> ${ENV_FILE} + echo "DOCKER_TLS_VERIFY=${DOCKER_TLS_VERIFY}" >> ${ENV_FILE} + echo "DOCKER_TLS_CERTDIR=${DOCKER_TLS_CERTDIR}" >> ${ENV_FILE} fi EXTRA_ARGS="" if [[ ! -z "${RUNNER_LABELS}" ]]; then EXTRA_ARGS="${EXTRA_ARGS} --labels ${RUNNER_LABELS}" fi +decho "EXTRA_ARGS: ${EXTRA_ARGS}" # Set the runner file if [[ -z "${RUNNER_FILE}" ]]; then - RUNNER_FILE=".runner.json" # use json so editors know how to highlight + RUNNER_FILE="runner.json" # use json so editors know how to highlight fi +decho "RUNNER_FILE: ${RUNNER_FILE}" sed -i "/^ file:/c\ file: ${RUNNER_FILE}" ${CONFIG_FILE} +if [[ "${SKIP_WAIT}" != "true" ]]; then + secho "Waiting 10s to allow other services to start up..." + sleep 10 +fi + if [[ ! -s "${RUNNER_FILE}" ]]; then touch ${RUNNER_FILE} try=$((try + 1)) success=0 + decho "try: ${try}, success: ${success}" if [[ ! -z "${FORGEJO_SECRET}" ]]; then EXTRA_ARGS="${EXTRA_ARGS} --secret ${FORGEJO_SECRET}" @@ -112,6 +142,7 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then EXTRA_ARGS="${EXTRA_ARGS} --token ${RUNNER_TOKEN}" echo "Registering with TOKEN" fi + decho "EXTRA_ARGS after secret/token: ${EXTRA_ARGS}" # The point of this loop is to make it simple, when running both forgejo-runner and gitea in docker, # for the forgejo-runner to wait a moment for gitea to become available before erroring out. Within @@ -131,10 +162,12 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then echo "Waiting to retry ..." sleep 5 fi + decho "try: ${try}, success: ${success}" done fi # Prevent reading the token from the forgejo-runner process unset RUNNER_TOKEN +unset FORGEJO_SECRET run_command "forgejo-runner daemon ${CONFIG_ARG}" diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index e38e841..e644a4f 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -7,7 +7,7 @@ # openssl rand -hex 20 # # Replace all occurences of {SHARED_SECRET} below with the output. -# +# # NOTE: a token obtained from the Forgejo web interface cannot be used # as a shared secret. # @@ -23,20 +23,19 @@ volumes: services: docker-in-docker: image: code.forgejo.org/oci/docker:dind - container_name: docker # needed for docker internal DNS resolution - hostname: docker # Must set hostname as TLS certificates are only valid for docker or localhost + # container_name: docker # Must set container_name to docker for both internal DNS and TLS to work + hostname: docker privileged: true networks: - forgejo environment: - DOCKER_TLS_CERTDIR: "" # set to "certs" to use the TLS certificates, also update existing runner configs to use port 2376 - DOCKER_HOST: docker-in-docker + DOCKER_TLS_CERTDIR: "/certs" # set to "" to disable the use of TLS, also manually update existing runner configs to use port 2375 volumes: - docker_certs:/certs forgejo: image: codeberg.org/forgejo/forgejo:1.21 - container_name: forgejo + hostname: forgejo networks: - forgejo volumes: @@ -47,20 +46,21 @@ services: bash -c ' /bin/s6-svscan /etc/s6 & sleep 10 ; + su -c "forgejo admin user create --admin --username root --password examplepassword --email root@example.com" git ; su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET}" git ; sleep infinity ' + # all values that have defaults listed are optional + # only FORGEJO_SECRET or RUNNER_TOKEN is required + # FORGEJO_URL is required if forgejo is in this compose file or docker network forgejo-runner: ## TODO: Update image to the the release ## made from this PR: https://code.forgejo.org/forgejo/runner/pulls/283 - - # image: code.forgejo.org/forgejo/runner:3.4.1 - build: - context: ../../ - dockerfile: Dockerfile - container_name: forgejo-runner - # user: "1000" # set to run rootless, overrides RUNNER_USER + + # image: code.forgejo.org/forgejo/runner:3.4.1 + build: ../../ + # user: "1000" # set to run rootless, overrides RUNNER_USER and disables automatic file ownership volumes: - ./forgejo-runner:/data - docker_certs:/certs @@ -70,39 +70,19 @@ services: - docker-in-docker - forgejo environment: - CONFIG_FILE: config.yml # defaults to /data/config.yml + CONFIG_FILE: config.yml # defaults to /data/config.yml - FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 - FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's + DOCKER_HOST: "docker" # defaults to docker + DOCKER_TLS_CERTDIR: "/certs/client" # defaults to /certs/client + DOCKER_TLS_VERIFY: "1" # defaults to 0, set to 1 to enable TLS - RUNNER_FILE: runner.json # defaults to /data/runner.json - RUNNER_NAME: forgejo-runner # defaults to forgejo-runner, used for registration + FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 + FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's, overrides RUNNER_TOKEN + + RUNNER_FILE: .runner # defaults to /data/runner.json + RUNNER_NAME: forgejo-runner # defaults to forgejo-runner, used for registration RUNNER_TOKEN: "${RUNNER_TOKEN}" - RUNNER_USER: 1000 # defaults to 1000 + RUNNER_USER: 1000 # defaults to 1000, allows for automatic file ownership - forgejo-runner-rootless: - ## TODO: Update image to the the release - ## made from this PR: https://code.forgejo.org/forgejo/runner/pulls/283 - - # image: code.forgejo.org/forgejo/runner:3.4.1 - build: - context: ../../ - dockerfile: Dockerfile.rootless - container_name: forgejo-runner-rootless - volumes: - - ./forgejo-runner:/data - - docker_certs:/certs - networks: - - forgejo - depends_on: - - docker-in-docker - - forgejo - environment: - CONFIG_FILE: config-rootless.yml # defaults to /data/config.yml - - FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 - FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's - - RUNNER_FILE: runner-rootless.json # defaults to /data/runner.json - RUNNER_NAME: forgejo-runner-rootless # defaults to forgejo-runner, used for registration - RUNNER_TOKEN: "${RUNNER_TOKEN}" \ No newline at end of file + DEBUG: "true" # defaults to false, set to true to enable debug logging + SKIP_WAIT: "false" # defaults to false, set to true to skip the 10 second wait to allow for forgejo and docker-in-docker to start -- 2.45.2 From f9ff5dce170bcea3780e8332b234f879cf8d239b Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Thu, 26 Sep 2024 15:16:51 -0700 Subject: [PATCH 09/18] echo, not secho --- entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entrypoint.sh b/entrypoint.sh index ed17b19..60622c4 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -121,7 +121,7 @@ decho "RUNNER_FILE: ${RUNNER_FILE}" sed -i "/^ file:/c\ file: ${RUNNER_FILE}" ${CONFIG_FILE} if [[ "${SKIP_WAIT}" != "true" ]]; then - secho "Waiting 10s to allow other services to start up..." + echo "Waiting 10s to allow other services to start up..." sleep 10 fi -- 2.45.2 From 00584cc415b5adb0e669e506d3d89f678748f902 Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Thu, 26 Sep 2024 19:00:54 -0700 Subject: [PATCH 10/18] I guess it works now sorry for the unprofessional commit message, I have been working on this effectively non-stop since the previous commit, and have been fighting docker networking being inconsistent as well as filepermisson issues, end me --- entrypoint.sh | 109 ++++++++++-------- .../compose-forgejo-and-runner.yml | 19 +-- 2 files changed, 74 insertions(+), 54 deletions(-) mode change 100644 => 100755 entrypoint.sh diff --git a/entrypoint.sh b/entrypoint.sh old mode 100644 new mode 100755 index 60622c4..bb72004 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,17 +4,28 @@ set -e run_command() { local cmd="$1" - redacted_cmd=$(echo "$cmd" | sed -E 's/(--secret\s+|--token\s+)[^ ]+/--\1[REDACTED]/g') - decho "Running command: $redacted_cmd" + + # Replace any --token or --secret with [REDACTED] + local safe_cmd=$(echo "$cmd" | sed -E 's/--(token|secret) [^ ]+/--\1 [REDACTED]/g') + + decho "Running command: $safe_cmd" + if [[ "$ISROOT" == true ]]; then decho "Running as forgejo-runner" su -c "$cmd" forgejo-runner else - decho "Running as RUNNER_USER: ${RUNNER_USER}" + decho "Running as $(whoami)" eval "$cmd" fi } +makeUser() { + adduser -u ${RUNNER_USER} -h /data -s /bin/bash -D forgejo-runner +} +makeGroup() { + addgroup -g ${RUNNER_USER} forgejo-runner +} + decho() { if [[ "${DEBUG}" == "true" ]]; then echo "[entrypoint] $@" @@ -33,27 +44,37 @@ if [[ $(id -u) -eq 0 ]]; then fi if [[ "$ISROOT" == true ]]; then - # Check if the forgejo-runner user exists - if id "forgejo-runner" &>/dev/null; then - echo "forgejo-runner user exists." - - # Change the user ID if needed - CURRENT_UID=$(id -u forgejo-runner) - decho "CURRENT_UID: ${CURRENT_UID}" - if [[ "${CURRENT_UID}" -ne "${RUNNER_USER}" ]]; then - echo "Changing UID of forgejo-runner to ${RUNNER_USER}" - sed -i "s/^forgejo-runner:[^:]*:[^:]*:/forgejo-runner:x:${RUNNER_USER}:/" /etc/passwd - fi + # Check if the forgejo-runner user exists, if not, create it + if ! id -u forgejo-runner >/dev/null 2>&1; then + decho "Creating user forgejo-runner with UID ${RUNNER_USER}" + makeUser else - echo "Creating user forgejo-runner with UID ${RUNNER_USER}" - adduser --uid "${RUNNER_USER}" --home /home/forgejo-runner --disabled-password --gecos "" forgejo-runner + CURRENT_UID=$(id -u forgejo-runner) + if [[ "${CURRENT_UID}" -ne "${RUNNER_USER}" ]]; then + decho "Changing UID of forgejo-runner from ${CURRENT_UID} to ${RUNNER_USER}" + deluser forgejo-runner + makeUser + fi + fi + + # Check if the forgejo-runner group exists, if not, create it + if ! getent group forgejo-runner >/dev/null 2>&1; then + decho "Creating group forgejo-runner with GID ${RUNNER_USER}" + makeGroup + else + CURRENT_GID=$(getent group forgejo-runner | cut -d: -f3) + if [[ "${CURRENT_GID}" -ne "${RUNNER_USER}" ]]; then + decho "Changing GID of forgejo-runner from ${CURRENT_GID} to ${RUNNER_USER}" + delgroup forgejo-runner + makeGroup + fi fi # Ensure /data is owned by the runner user - if [[ $(stat -c "%u" /data) != "${RUNNER_USER}" ]]; then - decho "Changing ownership of /data to ${RUNNER_USER}" - chown -R forgejo-runner:forgejo-runner /data - fi + # yes this can slow things down but is 100% nessecary for the runner to function + # when running as a root user, because for some reason the runner create files as + # root and then cant access them + chown -R forgejo-runner:forgejo-runner /data fi # Handle and alter the config file @@ -65,33 +86,33 @@ CONFIG_ARG="--config ${CONFIG_FILE}" decho "CONFIG: ${CONFIG_ARG}" DOCKER_HOST=${DOCKER_HOST:-docker} -DOCKER_TLS_CERTDIR=${DOCKER_TLS_CERTDIR:-"/certs/client"} +DOCKER_CERT_PATH=${DOCKER_CERT_PATH:-"/certs/client"} DOCKER_TLS_VERIFY=${DOCKER_TLS_VERIFY:-0} decho "DOCKER_HOST: ${DOCKER_HOST}" -decho "DOCKER_TLS_CERTDIR: ${DOCKER_TLS_CERTDIR}" +decho "DOCKER_CERT_PATH: ${DOCKER_CERT_PATH}" decho "DOCKER_TLS_VERIFY: ${DOCKER_TLS_VERIFY}" if [[ ! -f "${CONFIG_FILE}" ]]; then echo "Creating ${CONFIG_FILE}" - run_command "forgejo-runner generate-config > ${CONFIG_FILE}" forgejo-runner + run_command "forgejo-runner generate-config > ${CONFIG_FILE}" # Remove test environment variables if they exist in the config file sed -i "/^ A_TEST_ENV_NAME_1:/d" ${CONFIG_FILE} sed -i "/^ A_TEST_ENV_NAME_2:/d" ${CONFIG_FILE} # Apply default values for docker - sed -i "/^ labels:/c\ \"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} + sed -i "/^ labels:/c\ labels: [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} if [[ "${DOCKER_TLS_VERIFY}" -ne 1 ]]; then decho "Docker TLS diabled" - sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2375" ${CONFIG_FILE} + sed -i "/^ docker_host:/c\ docker_host: ${DOCKER_HOST}" ${CONFIG_FILE} else decho "Docker TLS enabled" - sed -i "/^ docker_host:/c\ docker_host: tcp://${DOCKER_HOST}:2376" ${CONFIG_FILE} - sed -i "/^ valid_volumes:/c\ valid_volumes:\n - ${DOCKER_TLS_CERTDIR}" ${CONFIG_FILE} - sed -i "/^ options:/c\ options: -v ${DOCKER_TLS_CERTDIR}:${DOCKER_TLS_CERTDIR}" ${CONFIG_FILE} + sed -i "/^ docker_host:/c\ docker_host: ${DOCKER_HOST}" ${CONFIG_FILE} + sed -i "/^ valid_volumes:/c\ valid_volumes:\n - ${DOCKER_CERT_PATH}" ${CONFIG_FILE} + sed -i "/^ options:/c\ options: -v ${DOCKER_CERT_PATH}:${DOCKER_CERT_PATH}" ${CONFIG_FILE} fi fi @@ -104,7 +125,7 @@ if [[ ! -f "${ENV_FILE}" ]]; then touch ${ENV_FILE} echo "DOCKER_HOST=${DOCKER_HOST}" >> ${ENV_FILE} echo "DOCKER_TLS_VERIFY=${DOCKER_TLS_VERIFY}" >> ${ENV_FILE} - echo "DOCKER_TLS_CERTDIR=${DOCKER_TLS_CERTDIR}" >> ${ENV_FILE} + echo "DOCKER_CERT_PATH=${DOCKER_CERT_PATH}" >> ${ENV_FILE} fi EXTRA_ARGS="" @@ -131,30 +152,28 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then success=0 decho "try: ${try}, success: ${success}" - if [[ ! -z "${FORGEJO_SECRET}" ]]; then - EXTRA_ARGS="${EXTRA_ARGS} --secret ${FORGEJO_SECRET}" - echo "Registering with SECRET" - else - if [[ -z "${RUNNER_TOKEN}" ]]; then - echo "RUNNER_TOKEN is not set" - exit 1 - fi - EXTRA_ARGS="${EXTRA_ARGS} --token ${RUNNER_TOKEN}" - echo "Registering with TOKEN" - fi - decho "EXTRA_ARGS after secret/token: ${EXTRA_ARGS}" - # The point of this loop is to make it simple, when running both forgejo-runner and gitea in docker, # for the forgejo-runner to wait a moment for gitea to become available before erroring out. Within # the context of a single docker-compose, something similar could be done via healthchecks, but # this is more flexible. while [[ $success -eq 0 ]] && [[ $try -lt ${MAX_REG_ATTEMPTS:-10} ]]; do + if [[ ! -z "${FORGEJO_SECRET}" ]]; then run_command "forgejo-runner create-runner-file --connect \ --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ --name \"${RUNNER_NAME:-$(hostname)}\" \ - ${CONFIG_ARG} ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" - - cat /tmp/reg.log | grep 'connection successful' >/dev/null + --secret \"${FORGEJO_SECRET}\" \ + ${CONFIG_ARG}\ + ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" + else + run_command "forgejo-runner register \ + --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ + --name \"${RUNNER_NAME:-$(hostname)}\" \ + --token \"${RUNNER_TOKEN}\" \ + --no-interactive \ + ${CONFIG_ARG}\ + ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" + fi + cat /tmp/reg.log | grep -E 'connection successful|registered successfully' >/dev/null if [[ $? -eq 0 ]]; then echo "SUCCESS" success=1 diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index e644a4f..a2d1fa5 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -23,13 +23,13 @@ volumes: services: docker-in-docker: image: code.forgejo.org/oci/docker:dind - # container_name: docker # Must set container_name to docker for both internal DNS and TLS to work - hostname: docker + hostname: docker # Must set hostname for both internal DNS and TLS to work as certs are only valid for docker and localhost privileged: true networks: - forgejo environment: DOCKER_TLS_CERTDIR: "/certs" # set to "" to disable the use of TLS, also manually update existing runner configs to use port 2375 + DOCKER_HOST: "docker" # remove aswell to disable TLS volumes: - docker_certs:/certs @@ -39,7 +39,7 @@ services: networks: - forgejo volumes: - - ./forgejo:/data + - /srv/forgejo-data:/data ports: - 8080:3000 command: >- @@ -54,15 +54,16 @@ services: # all values that have defaults listed are optional # only FORGEJO_SECRET or RUNNER_TOKEN is required # FORGEJO_URL is required if forgejo is in this compose file or docker network - forgejo-runner: + runner-daemon: ## TODO: Update image to the the release ## made from this PR: https://code.forgejo.org/forgejo/runner/pulls/283 # image: code.forgejo.org/forgejo/runner:3.4.1 build: ../../ # user: "1000" # set to run rootless, overrides RUNNER_USER and disables automatic file ownership + restart: unless-stopped # needed for fixing file ownership on restart volumes: - - ./forgejo-runner:/data + - /srv/runner-data:/data - docker_certs:/certs networks: - forgejo @@ -72,16 +73,16 @@ services: environment: CONFIG_FILE: config.yml # defaults to /data/config.yml - DOCKER_HOST: "docker" # defaults to docker - DOCKER_TLS_CERTDIR: "/certs/client" # defaults to /certs/client + DOCKER_HOST: "tcp://docker:2376" # defaults to tcp://docker:2376 + DOCKER_CERT_PATH: "/certs/client" # defaults to /certs/client DOCKER_TLS_VERIFY: "1" # defaults to 0, set to 1 to enable TLS FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's, overrides RUNNER_TOKEN RUNNER_FILE: .runner # defaults to /data/runner.json - RUNNER_NAME: forgejo-runner # defaults to forgejo-runner, used for registration - RUNNER_TOKEN: "${RUNNER_TOKEN}" + RUNNER_NAME: runner-daemon # defaults to forgejo-runner, used for registration + RUNNER_TOKEN: ${RUNNER_TOKEN} # token obtained from Forgejo web interface RUNNER_USER: 1000 # defaults to 1000, allows for automatic file ownership DEBUG: "true" # defaults to false, set to true to enable debug logging -- 2.45.2 From 42078da550cc37003156fa9127c203b09b0ff0b1 Mon Sep 17 00:00:00 2001 From: Merith Date: Fri, 27 Sep 2024 10:38:59 -0700 Subject: [PATCH 11/18] dont use root-user by default --- .forgejo/workflows/example-docker-compose.yml | 2 +- Dockerfile | 2 + entrypoint.sh | 89 +++---------------- examples/docker-compose/.gitignore | 3 +- .../compose-forgejo-and-runner.yml | 19 ++-- 5 files changed, 26 insertions(+), 89 deletions(-) diff --git a/.forgejo/workflows/example-docker-compose.yml b/.forgejo/workflows/example-docker-compose.yml index f1089ec..4e2f547 100644 --- a/.forgejo/workflows/example-docker-compose.yml +++ b/.forgejo/workflows/example-docker-compose.yml @@ -67,4 +67,4 @@ jobs: if: always() run: | cd examples/docker-compose - docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml logs \ No newline at end of file + docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml logs diff --git a/Dockerfile b/Dockerfile index ed94063..af507da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,6 +38,8 @@ LABEL maintainer="contact@forgejo.org" \ ENV HOME=/data +USER 1000:1000 + COPY --chmod=555 entrypoint.sh /entrypoint.sh WORKDIR /data diff --git a/entrypoint.sh b/entrypoint.sh index bb72004..64ec4f7 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,28 +2,13 @@ set -e +# Technically not nessecary but it cleans up the logs from having token/secret values run_command() { local cmd="$1" - # Replace any --token or --secret with [REDACTED] local safe_cmd=$(echo "$cmd" | sed -E 's/--(token|secret) [^ ]+/--\1 [REDACTED]/g') - decho "Running command: $safe_cmd" - - if [[ "$ISROOT" == true ]]; then - decho "Running as forgejo-runner" - su -c "$cmd" forgejo-runner - else - decho "Running as $(whoami)" - eval "$cmd" - fi -} - -makeUser() { - adduser -u ${RUNNER_USER} -h /data -s /bin/bash -D forgejo-runner -} -makeGroup() { - addgroup -g ${RUNNER_USER} forgejo-runner + eval "$cmd" } decho() { @@ -32,49 +17,10 @@ decho() { fi } -# Initial setup -cd /data - -decho "RUNNER_USER: ${RUNNER_USER}" -RUNNER_USER="${RUNNER_USER:-1000}" # Check if the script is running as root if [[ $(id -u) -eq 0 ]]; then ISROOT=true - decho "Running as root" -fi - -if [[ "$ISROOT" == true ]]; then - # Check if the forgejo-runner user exists, if not, create it - if ! id -u forgejo-runner >/dev/null 2>&1; then - decho "Creating user forgejo-runner with UID ${RUNNER_USER}" - makeUser - else - CURRENT_UID=$(id -u forgejo-runner) - if [[ "${CURRENT_UID}" -ne "${RUNNER_USER}" ]]; then - decho "Changing UID of forgejo-runner from ${CURRENT_UID} to ${RUNNER_USER}" - deluser forgejo-runner - makeUser - fi - fi - - # Check if the forgejo-runner group exists, if not, create it - if ! getent group forgejo-runner >/dev/null 2>&1; then - decho "Creating group forgejo-runner with GID ${RUNNER_USER}" - makeGroup - else - CURRENT_GID=$(getent group forgejo-runner | cut -d: -f3) - if [[ "${CURRENT_GID}" -ne "${RUNNER_USER}" ]]; then - decho "Changing GID of forgejo-runner from ${CURRENT_GID} to ${RUNNER_USER}" - delgroup forgejo-runner - makeGroup - fi - fi - - # Ensure /data is owned by the runner user - # yes this can slow things down but is 100% nessecary for the runner to function - # when running as a root user, because for some reason the runner create files as - # root and then cant access them - chown -R forgejo-runner:forgejo-runner /data + decho "[WARNING] Running as root user" fi # Handle and alter the config file @@ -85,9 +31,9 @@ fi CONFIG_ARG="--config ${CONFIG_FILE}" decho "CONFIG: ${CONFIG_ARG}" -DOCKER_HOST=${DOCKER_HOST:-docker} +DOCKER_HOST=${DOCKER_HOST:-"tcp://docker:2367"} DOCKER_CERT_PATH=${DOCKER_CERT_PATH:-"/certs/client"} -DOCKER_TLS_VERIFY=${DOCKER_TLS_VERIFY:-0} +DOCKER_TLS_VERIFY=${DOCKER_TLS_VERIFY:-1} decho "DOCKER_HOST: ${DOCKER_HOST}" decho "DOCKER_CERT_PATH: ${DOCKER_CERT_PATH}" decho "DOCKER_TLS_VERIFY: ${DOCKER_TLS_VERIFY}" @@ -102,18 +48,7 @@ if [[ ! -f "${CONFIG_FILE}" ]]; then # Apply default values for docker sed -i "/^ labels:/c\ labels: [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} - sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} - - if [[ "${DOCKER_TLS_VERIFY}" -ne 1 ]]; then - decho "Docker TLS diabled" - sed -i "/^ docker_host:/c\ docker_host: ${DOCKER_HOST}" ${CONFIG_FILE} - else - decho "Docker TLS enabled" - sed -i "/^ docker_host:/c\ docker_host: ${DOCKER_HOST}" ${CONFIG_FILE} - sed -i "/^ valid_volumes:/c\ valid_volumes:\n - ${DOCKER_CERT_PATH}" ${CONFIG_FILE} - sed -i "/^ options:/c\ options: -v ${DOCKER_CERT_PATH}:${DOCKER_CERT_PATH}" ${CONFIG_FILE} - fi fi ENV_FILE=${ENV_FILE:-"/data/.env"} @@ -135,9 +70,7 @@ fi decho "EXTRA_ARGS: ${EXTRA_ARGS}" # Set the runner file -if [[ -z "${RUNNER_FILE}" ]]; then - RUNNER_FILE="runner.json" # use json so editors know how to highlight -fi +RUNNER_FILE=${RUNNER_FILE:-"runner.json"} # use json so editors know how to highlight decho "RUNNER_FILE: ${RUNNER_FILE}" sed -i "/^ file:/c\ file: ${RUNNER_FILE}" ${CONFIG_FILE} @@ -157,22 +90,22 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then # the context of a single docker-compose, something similar could be done via healthchecks, but # this is more flexible. while [[ $success -eq 0 ]] && [[ $try -lt ${MAX_REG_ATTEMPTS:-10} ]]; do - if [[ ! -z "${FORGEJO_SECRET}" ]]; then - run_command "forgejo-runner create-runner-file --connect \ + if [[ ! -z "${FORGEJO_SECRET}" ]]; then + run_command "forgejo-runner create-runner-file --connect \ --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ --name \"${RUNNER_NAME:-$(hostname)}\" \ --secret \"${FORGEJO_SECRET}\" \ ${CONFIG_ARG}\ ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" - else - run_command "forgejo-runner register \ + else + run_command "forgejo-runner register \ --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ --name \"${RUNNER_NAME:-$(hostname)}\" \ --token \"${RUNNER_TOKEN}\" \ --no-interactive \ ${CONFIG_ARG}\ ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" - fi + fi cat /tmp/reg.log | grep -E 'connection successful|registered successfully' >/dev/null if [[ $? -eq 0 ]]; then echo "SUCCESS" diff --git a/examples/docker-compose/.gitignore b/examples/docker-compose/.gitignore index 294fcad..94bf3ec 100644 --- a/examples/docker-compose/.gitignore +++ b/examples/docker-compose/.gitignore @@ -1,2 +1 @@ -forgejo/ -forgejo-runner/ +srv diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index a2d1fa5..6431893 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -13,7 +13,8 @@ # # Replace ${RUNNER_TOKEN} with the token obtained from the Forgejo web interface. # - +# Replace ROOT_PASSWORD with a secure password. +# networks: forgejo: @@ -24,12 +25,13 @@ services: docker-in-docker: image: code.forgejo.org/oci/docker:dind hostname: docker # Must set hostname for both internal DNS and TLS to work as certs are only valid for docker and localhost + restart: unless-stopped privileged: true networks: - forgejo environment: DOCKER_TLS_CERTDIR: "/certs" # set to "" to disable the use of TLS, also manually update existing runner configs to use port 2375 - DOCKER_HOST: "docker" # remove aswell to disable TLS + DOCKER_HOST: "docker" # remove aswell to disable TLS volumes: - docker_certs:/certs @@ -42,25 +44,27 @@ services: - /srv/forgejo-data:/data ports: - 8080:3000 + environment: + FORGEJO__security__INSTALL_LOCK: "true" # remove in production command: >- bash -c ' /bin/s6-svscan /etc/s6 & sleep 10 ; - su -c "forgejo admin user create --admin --username root --password examplepassword --email root@example.com" git ; + su -c "forgejo admin user create --admin --username root --password ROOT_PASSWORD --email root@example.com" git ; su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET}" git ; sleep infinity ' # all values that have defaults listed are optional - # only FORGEJO_SECRET or RUNNER_TOKEN is required - # FORGEJO_URL is required if forgejo is in this compose file or docker network + # only FORGEJO_SECRET or RUNNER_TOKEN is required, the secret will be prioritized + # FORGEJO_URL is required if forgejo is not in this compose file or docker network runner-daemon: ## TODO: Update image to the the release ## made from this PR: https://code.forgejo.org/forgejo/runner/pulls/283 # image: code.forgejo.org/forgejo/runner:3.4.1 build: ../../ - # user: "1000" # set to run rootless, overrides RUNNER_USER and disables automatic file ownership + user: "1000" # defaults to 1000, restart: unless-stopped # needed for fixing file ownership on restart volumes: - /srv/runner-data:/data @@ -75,7 +79,7 @@ services: DOCKER_HOST: "tcp://docker:2376" # defaults to tcp://docker:2376 DOCKER_CERT_PATH: "/certs/client" # defaults to /certs/client - DOCKER_TLS_VERIFY: "1" # defaults to 0, set to 1 to enable TLS + DOCKER_TLS_VERIFY: "1" # defaults to 1 FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's, overrides RUNNER_TOKEN @@ -83,7 +87,6 @@ services: RUNNER_FILE: .runner # defaults to /data/runner.json RUNNER_NAME: runner-daemon # defaults to forgejo-runner, used for registration RUNNER_TOKEN: ${RUNNER_TOKEN} # token obtained from Forgejo web interface - RUNNER_USER: 1000 # defaults to 1000, allows for automatic file ownership DEBUG: "true" # defaults to false, set to true to enable debug logging SKIP_WAIT: "false" # defaults to false, set to true to skip the 10 second wait to allow for forgejo and docker-in-docker to start -- 2.45.2 From 95fb2cafff645a2eb0b026b59e1eb54f81a85b36 Mon Sep 17 00:00:00 2001 From: Merith Date: Fri, 27 Sep 2024 10:46:35 -0700 Subject: [PATCH 12/18] fix Kind/Breaking tag --- entrypoint.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/entrypoint.sh b/entrypoint.sh index 64ec4f7..db9291f 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,7 +4,7 @@ set -e # Technically not nessecary but it cleans up the logs from having token/secret values run_command() { - local cmd="$1" + local cmd="$@" # Replace any --token or --secret with [REDACTED] local safe_cmd=$(echo "$cmd" | sed -E 's/--(token|secret) [^ ]+/--\1 [REDACTED]/g') decho "Running command: $safe_cmd" @@ -23,6 +23,12 @@ if [[ $(id -u) -eq 0 ]]; then decho "[WARNING] Running as root user" fi +# Handle if `command` is passed, as command appends arguments to the entrypoint +if [ "$#" -gt 0 ]; then + run_command "$@" + exit +fi + # Handle and alter the config file if [[ -z "${CONFIG_FILE}" ]]; then echo "CONFIG_FILE is not set" -- 2.45.2 From 890778d33ad275cf8dabc2b0e18c004ed2b46f8f Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Fri, 27 Sep 2024 11:08:56 -0700 Subject: [PATCH 13/18] resolve tag Kind/Breaks Docker treats "command" as an agument to an entrypoint if it exists, now the entrypoint runs arguments as if they were a command --- entrypoint.sh | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index db9291f..712227e 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -8,7 +8,7 @@ run_command() { # Replace any --token or --secret with [REDACTED] local safe_cmd=$(echo "$cmd" | sed -E 's/--(token|secret) [^ ]+/--\1 [REDACTED]/g') decho "Running command: $safe_cmd" - eval "$cmd" + eval $cmd } decho() { @@ -16,6 +16,7 @@ decho() { echo "[entrypoint] $@" fi } +decho $PWD # Check if the script is running as root if [[ $(id -u) -eq 0 ]]; then @@ -25,7 +26,7 @@ fi # Handle if `command` is passed, as command appends arguments to the entrypoint if [ "$#" -gt 0 ]; then - run_command "$@" + run_command $@ exit fi @@ -97,20 +98,20 @@ if [[ ! -s "${RUNNER_FILE}" ]]; then # this is more flexible. while [[ $success -eq 0 ]] && [[ $try -lt ${MAX_REG_ATTEMPTS:-10} ]]; do if [[ ! -z "${FORGEJO_SECRET}" ]]; then - run_command "forgejo-runner create-runner-file --connect \ - --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ - --name \"${RUNNER_NAME:-$(hostname)}\" \ - --secret \"${FORGEJO_SECRET}\" \ + run_command forgejo-runner create-runner-file --connect \ + --instance "${FORGEJO_URL:-http://forgejo:3000}" \ + --name "${RUNNER_NAME:-$(hostname)}" \ + --secret "${FORGEJO_SECRET}" \ ${CONFIG_ARG}\ - ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" + ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log else - run_command "forgejo-runner register \ - --instance \"${FORGEJO_URL:-http://forgejo:3000}\" \ - --name \"${RUNNER_NAME:-$(hostname)}\" \ - --token \"${RUNNER_TOKEN}\" \ + run_command forgejo-runner register \ + --instance "${FORGEJO_URL:-http://forgejo:3000}" \ + --name "${RUNNER_NAME:-$(hostname)}" \ + --token "${RUNNER_TOKEN}" \ --no-interactive \ ${CONFIG_ARG}\ - ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log" + ${EXTRA_ARGS} 2>&1 | tee /tmp/reg.log fi cat /tmp/reg.log | grep -E 'connection successful|registered successfully' >/dev/null if [[ $? -eq 0 ]]; then @@ -128,4 +129,4 @@ fi unset RUNNER_TOKEN unset FORGEJO_SECRET -run_command "forgejo-runner daemon ${CONFIG_ARG}" +run_command forgejo-runner daemon ${CONFIG_ARG} -- 2.45.2 From 8e05b3013bfae76e5ed3a712fa403482aa7d29bc Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Sat, 28 Sep 2024 09:28:52 -0700 Subject: [PATCH 14/18] force perms on /srv/runner-data --- .forgejo/workflows/example-docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.forgejo/workflows/example-docker-compose.yml b/.forgejo/workflows/example-docker-compose.yml index 4e2f547..ffb86c0 100644 --- a/.forgejo/workflows/example-docker-compose.yml +++ b/.forgejo/workflows/example-docker-compose.yml @@ -31,6 +31,8 @@ jobs: - name: run the example run: | set -x + mkdir -p /srv/runner-data + chown 1000:1000 /srv/runner-data cd examples/docker-compose secret=$(openssl rand -hex 20) sed -i -e "s/{SHARED_SECRET}/$secret/" compose-forgejo-and-runner.yml -- 2.45.2 From 962c6a62bb76f091a9b710e06e57316975d01d79 Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Sat, 28 Sep 2024 10:10:48 -0700 Subject: [PATCH 15/18] remove orphans - revert if fail --- .forgejo/workflows/example-docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/example-docker-compose.yml b/.forgejo/workflows/example-docker-compose.yml index ffb86c0..e84400f 100644 --- a/.forgejo/workflows/example-docker-compose.yml +++ b/.forgejo/workflows/example-docker-compose.yml @@ -40,7 +40,7 @@ jobs: # # Launch Forgejo & the runner # - $cli up -d + $cli up -d --remove-orphans for delay in $(seq 60) ; do test -f /srv/runner-data/.runner && break ; sleep 30 ; done test -f /srv/runner-data/.runner # -- 2.45.2 From 6b996253cfa3c9b4a3b775920e35adb199a29bd8 Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Sat, 28 Sep 2024 10:31:13 -0700 Subject: [PATCH 16/18] nuke network --- .../compose-forgejo-and-runner.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index 6431893..4229d85 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -13,11 +13,8 @@ # # Replace ${RUNNER_TOKEN} with the token obtained from the Forgejo web interface. # -# Replace ROOT_PASSWORD with a secure password. +# Replace {ROOT_PASSWORD} with a secure password. # -networks: - forgejo: - volumes: docker_certs: @@ -27,8 +24,6 @@ services: hostname: docker # Must set hostname for both internal DNS and TLS to work as certs are only valid for docker and localhost restart: unless-stopped privileged: true - networks: - - forgejo environment: DOCKER_TLS_CERTDIR: "/certs" # set to "" to disable the use of TLS, also manually update existing runner configs to use port 2375 DOCKER_HOST: "docker" # remove aswell to disable TLS @@ -38,8 +33,6 @@ services: forgejo: image: codeberg.org/forgejo/forgejo:1.21 hostname: forgejo - networks: - - forgejo volumes: - /srv/forgejo-data:/data ports: @@ -50,7 +43,7 @@ services: bash -c ' /bin/s6-svscan /etc/s6 & sleep 10 ; - su -c "forgejo admin user create --admin --username root --password ROOT_PASSWORD --email root@example.com" git ; + su -c "forgejo admin user create --admin --username root --password {ROOT_PASSWORD} --email root@example.com" git ; su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET}" git ; sleep infinity ' @@ -69,11 +62,12 @@ services: volumes: - /srv/runner-data:/data - docker_certs:/certs - networks: - - forgejo depends_on: - docker-in-docker - forgejo + links: + - forgejo + - docker-in-docker environment: CONFIG_FILE: config.yml # defaults to /data/config.yml -- 2.45.2 From f91070ea56c33f720f3a4c16a158e5aa405b1bcf Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Sat, 28 Sep 2024 10:36:47 -0700 Subject: [PATCH 17/18] restore original variables --- examples/docker-compose/compose-forgejo-and-runner.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index 4229d85..47d1965 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -39,6 +39,11 @@ services: - 8080:3000 environment: FORGEJO__security__INSTALL_LOCK: "true" # remove in production + FORGEJO__log__LEVEL: "debug" # remove in production + FORGEJO__repository__ENABLE_PUSH_CREATE_USER: "true" # enables the ability to create a repo when pushing + FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE: "false" # defaults above to public + FORGEJO__repository__DEFAULT_REPO_UNITS: "repo.code,repo.actions" + # `command` is not neecessary, but can be used to create an admin user as shown below when combined with INSTALL_LOCK command: >- bash -c ' /bin/s6-svscan /etc/s6 & -- 2.45.2 From ae1e54a796affe7260e4f7d30de8beb7a0bb0d31 Mon Sep 17 00:00:00 2001 From: merith-xyz Date: Sat, 28 Sep 2024 11:08:20 -0700 Subject: [PATCH 18/18] update to include privileged variable --- entrypoint.sh | 6 ++++++ examples/docker-compose/compose-forgejo-and-runner.yml | 1 + 2 files changed, 7 insertions(+) diff --git a/entrypoint.sh b/entrypoint.sh index 712227e..355bdd9 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -56,6 +56,12 @@ if [[ ! -f "${CONFIG_FILE}" ]]; then sed -i "/^ labels:/c\ labels: [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]" ${CONFIG_FILE} sed -i "/^ network:/c\ network: host" ${CONFIG_FILE} + if [[ "${DOCKER_PRIVILEGED}" == "true" ]]; then + sed -i "/^ privileged:/c\ privileged: true" ${CONFIG_FILE} + sed -i "/^ options:/c\ options:-v /certs/client:/certs/client" ${CONFIG_FILE} + sed -i "/^ valid_volumes:/c\ valid_volumes:\n - /certs/client" ${CONFIG_FILE} + fi + fi ENV_FILE=${ENV_FILE:-"/data/.env"} diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml index 47d1965..018d956 100644 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ b/examples/docker-compose/compose-forgejo-and-runner.yml @@ -79,6 +79,7 @@ services: DOCKER_HOST: "tcp://docker:2376" # defaults to tcp://docker:2376 DOCKER_CERT_PATH: "/certs/client" # defaults to /certs/client DOCKER_TLS_VERIFY: "1" # defaults to 1 + DOCKER_PRIVILEGED: "true" # defaults to false for security reasons FORGEJO_URL: ${FORGEJO_URL} # defaults to http://forgejo:3000 FORGEJO_SECRET: "{SHARED_SECRET}" # shared secret, must match Forgejo's, overrides RUNNER_TOKEN -- 2.45.2