Commit Graph

72 Commits

Author SHA1 Message Date
jason 5a46d8f868 🐛 Respect DOMAIN env var for gitea server name 🐛
REPLACE_SERVER_NAME and the dynamic ROOT_URL/DOMAIN/SSH_DOMAIN
re-stamps were using $HOSTNAME directly, ignoring the DOMAIN env
var passed in docker run. SERVER_NAME is already set to
${DOMAIN:-$HOSTNAME}; feed it back into FULL_DOMAIN_NAME so
__initialize_replace_variables picks it up, and switch the sed
re-stamps to use $SERVER_NAME.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: export
FULL_DOMAIN_NAME from SERVER_NAME; use SERVER_NAME in
ROOT_URL/DOMAIN/SSH_DOMAIN sed re-stamps

rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-06-09 19:04:04 -04:00
jason 42d0439d94 🐛 Use marker file to gate config seeding — never re-seed on restart 🐛
Replace the fragile grep-for-REPLACE_ re-seed check with a
.initialized marker written after __update_conf_files completes.
The seed (cp from /etc/ → /config/) only runs when the marker
is absent, so secrets and tokens are generated exactly once and
never overwritten on container restart.
To force a full re-initialisation: delete /config/$svc/.initialized
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: seed on missing
marker; write marker at end of __update_conf_files
- rootfs/usr/local/etc/docker/init.d/05-dockerd.sh: same
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: same

rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-09 18:57:12 -04:00
jason 2a5f7bdbc9 🐛 Re-seed config if REPLACE_ tokens remain from a broken prior run 🐛
The previous guard (check for missing primary config file) left
stale app.ini/daemon.json/default_config.yaml files in place when
the volume had an unprocessed copy from a broken earlier run.
Gitea then read REPLACE_DATABASE_DIR as a literal path, failed to
open the SQLite DB, and redirected to the install wizard.
Now also re-copy from /etc if the existing config file still
contains any REPLACE_ token, ensuring a clean template is always
in place before variable substitution runs.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: re-seed if
REPLACE_ tokens present in app.ini
- rootfs/usr/local/etc/docker/init.d/05-dockerd.sh: re-seed if
REPLACE_ tokens present in daemon.json
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: re-seed if
REPLACE_ tokens present in default_config.yaml

rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-09 16:07:12 -04:00
jason 6b8527c19b 🐛 Fix config seed check and container env var mapping 🐛
Guard the /etc→/config seed on the primary config file rather
than dir-empty so a pre-existing volume with only subdirs (e.g.
custom/) does not prevent app.ini/daemon.json/default_config.yaml
from being seeded — fixing the gitea install-page regression.
Also wire CONTAINER_DEFAULT_DATABASE_TYPE, CONTAINER_PROTOCOL,
CONTAINER_WEB_SERVER_PROTOCOL, WEB_PORT/ENV_PORTS, and
DATABASE_DIR_SQLITE to the correct gitea init variables so all
REPLACE_* tokens in app.ini are substituted on first start.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: seed guard
checks for app.ini; map CONTAINER_DEFAULT_DATABASE_TYPE →
GITEA_SQL_TYPE; map CONTAINER_PROTOCOL/WEB_PORT → SERVICE_*;
fix DATABASE_DIR and CUSTOM_PATH
- rootfs/usr/local/etc/docker/init.d/05-dockerd.sh: seed guard
checks for daemon.json
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: seed guard
checks for default_config.yaml

rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-09 15:52:09 -04:00
jason 963dbf8ab5 🐛 Map container env vars to gitea init variables 🐛
Wire CONTAINER_DEFAULT_DATABASE_TYPE, CONTAINER_PROTOCOL,
CONTAINER_WEB_SERVER_PROTOCOL, WEB_PORT, ENV_PORTS, and
DATABASE_DIR_SQLITE to the correct gitea init variables so
all REPLACE_* tokens in app.ini are substituted correctly
on first container start.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: map
CONTAINER_DEFAULT_DATABASE_TYPE → DATABASE_SERVICE_TYPE +
GITEA_SQL_TYPE (sqlite→sqlite3, postgres, mysql, mssql);
map CONTAINER_PROTOCOL/CONTAINER_WEB_SERVER_PROTOCOL →
SERVICE_PROTOCOL; map WEB_PORT/ENV_PORTS → SERVICE_PORT;
initialise DATABASE_DIR from DATABASE_DIR_SQLITE env var;
fix CUSTOM_PATH export to point at $CONF_DIR/custom

.claude/settings.local.json
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-06-09 15:39:38 -04:00
jason c7b724bf4b ♻️ symlink ETC_DIR to CONF_DIR instead of dual-copy ♻️
- Replace copy-on-first-run + `__initialize_system_etc` sync loop with a symlink: after seeding `$CONF_DIR`, remove `$ETC_DIR` and point it at `$CONF_DIR` so both paths always resolve to the same config
- Drop `$ETC_DIR` from `__initialize_replace_variables` calls since the symlink makes it redundant
- Switch daemon.json, app.ini, and runner yaml config paths from `$ETC_DIR` to `$CONF_DIR` references
- Remove unused `__init_config_etc` function from entrypoint.sh

rootfs/usr/local/etc/docker/functions/entrypoint.sh
rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-09 15:08:17 -04:00
jason ead2bd2e19 🗃️ Update codebase 🗃️
rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-09 14:38:20 -04:00
jason 36854be70b 🐛 Update entrypoint.sh and functions library from current template 🐛
Stale copies called __initialize_default_templates, __initialize_config_dir,
and __initialize_data_dir which are not in the old functions library,
causing container startup failures. Replaced with current template
versions (202606041210-git) which no longer call those missing functions.
- rootfs/usr/local/bin/entrypoint.sh: update to current template
- rootfs/usr/local/etc/docker/functions/entrypoint.sh: update to current template

.claude/settings.local.json
Dockerfile
.env.scripts
rootfs/usr/local/bin/entrypoint.sh
2026-06-05 18:24:48 -04:00
jason 056270d60c 🐛 Update entrypoint.sh and functions library from current template 🐛
The gitea repo had stale copies of both files. The old entrypoint.sh
called __initialize_default_templates, __initialize_config_dir, and
__initialize_data_dir which don't exist in the old functions library,
causing container startup failures.
Replace both with the current template versions (202606041210-git).
The new entrypoint.sh no longer calls those missing functions.
Set CONTAINER_NAME=gitea and description to match the service.
- rootfs/usr/local/bin/entrypoint.sh: update to 202606041210-git template
- rootfs/usr/local/etc/docker/functions/entrypoint.sh: update to current template

.claude/settings.local.json
rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/etc/docker/functions/entrypoint.sh
2026-06-05 18:06:48 -04:00
jason c420852e0b 🐛 Set WORK_DIR for act_runner to avoid /root permission issues 🐛
act_runner runs as the git user which has no access to /root (Docker's
WORKDIR). Setting WORK_DIR=/data/act_runner ensures the service starts
from a directory the git user can access, preventing any git or file
operations from inadvertently referencing /root.
05-dockerd.sh runs as root so no fix needed there.
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: set WORK_DIR=/data/act_runner

rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-05 17:41:48 -04:00
jason 0ff1923d3e 🐛 Fix git fatal error reading /root/.git at gitea startup 🐛
Docker's WORKDIR is /root and the git user has no read permission on
that directory. When gitea starts via gosu git, git inherits /root as
the working directory, calls getcwd(), constructs /root/.git, and
fails with "fatal: error reading '/root/.git'" — crashing gitea.
Setting WORK_DIR=/data/gitea causes the init functions library to cd
to /data/gitea before launching the service, so git never sees /root.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: set WORK_DIR=/data/gitea

rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-06-05 17:40:04 -04:00
jason 7e6f4f5a84 🐛 Fix chmod error on empty ssh directory at first run 🐛
chmod 0600 $DATA_DIR/ssh/* fails with "cannot access" when the
directory is empty (first boot before keys are generated, or when
keys are symlinks in /config/ssh). Replace the glob with find -type f
which silently handles empty directories.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: use find -exec chmod instead of glob for ssh key permissions

rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-06-05 17:38:17 -04:00
jason 1cc1624187 🐛 Remove :host runner labels — all jobs must run in containers 🐛
:host labels run jobs directly on the container filesystem with no
isolation. Replace all arch-specific :host labels with
:docker://ubuntu:latest so every job runs inside its own container
regardless of the runner host architecture.
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: amd64/arm64/linux labels use docker://ubuntu:latest not :host
- README.md: remove :host from external runner label examples

README.md
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-05 17:06:16 -04:00
jason e624d7c219 Add arch-specific runner labels for native amd64/arm64 matrix builds
Detect the host architecture at container startup and prepend
arch-specific labels to RUNNER_LABELS so matrix workflows can target
native runners by architecture:
runs-on: amd64 → dispatched to x86_64 runners
runs-on: arm64 → dispatched to aarch64 runners
runs-on: linux/amd64 / runs-on: linux/arm64 (OCI-style)
On x86_64: adds amd64:host and linux/amd64:host
On aarch64: adds arm64:host and linux/arm64:host
This enables a dedicated ARM64 server running the same image to register
native arm64 runners against the same Gitea instance, allowing full
multi-arch matrix CI without emulation.
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: detect arch, prepend arch labels to RUNNER_LABELS

rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-05 17:01:24 -04:00
jason 51a57cfeb4 Add DEFAULT_FORK_REPO_UNITS — full feature set for forks too
Forks should get the same full set of units as new repos since the
intent is a full GitHub migration. Matches DEFAULT_REPO_UNITS exactly.
- rootfs/tmp/etc/gitea/app.ini: add DEFAULT_FORK_REPO_UNITS with all units

rootfs/tmp/etc/gitea/app.ini
2026-06-05 16:49:07 -04:00
jason 85ccdabe5d Enable Actions by default on all new repos
Add DEFAULT_REPO_UNITS to [repository] in app.ini with repo.actions
included so every new repo has Actions enabled out of the box.
Users can still disable it per-repo — opt-out rather than opt-in.
- rootfs/tmp/etc/gitea/app.ini: add DEFAULT_REPO_UNITS with repo.actions included

rootfs/tmp/etc/gitea/app.ini
2026-06-05 16:47:18 -04:00
jason cd977be93d 🐛 Re-apply resolv.conf in init.d phase to beat Docker's async rewrite 🐛
Docker writes /etc/resolv.conf at container start before PID1 launches,
and again asynchronously when the network finishes initializing. The
entrypoint's early copy gets overwritten by Docker's second write.
Re-applying the custom resolv.conf in __run_precopy (init.d phase)
happens after Docker's network setup is complete, so the search . and
options ndots:0 settings stick for the full container lifetime.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: copy custom resolv.conf in __run_precopy

rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-06-05 15:44:44 -04:00
jason ea11289300 🔧 update resolv.conf in rootfs 🔧
- Update DNS resolver configuration in rootfs/usr/local/etc/resolv.conf

rootfs/usr/local/etc/resolv.conf
2026-06-05 14:40:27 -04:00
jason 958439b9ee 🐛 Fix DATABASE_DIR_SQLITE override; 📝 correct docker run example 🐛
DATABASE_DIR fix:
The previous override hardcoded $DATA_DIR/db/sqlite, ignoring
DATABASE_DIR_SQLITE when it was explicitly set via env var. Changed
to respect DATABASE_DIR_SQLITE and only fall back to $DATA_DIR/db/sqlite
when the env var is not provided.
README:
- docker run and compose examples updated to match actual working flags:
--cgroupns private, --tty, --cap-add CHOWN/SYS_TIME/SYS_ADMIN,
--hostname FQDN, --domainname, GITEA_PROTO, DATABASE_DIR_SQLITE
with a separate sqlite volume mount
- Removed non-functional vars from examples (CONTAINER_PROTOCOL,
CONTAINER_DEFAULT_DATABASE_TYPE, DATABASE_BASE_DIR, WEB_PORT)
- Added DATABASE_DIR_SQLITE to the database env var table
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: respect DATABASE_DIR_SQLITE env var
- README.md: fix docker run/compose examples, add DATABASE_DIR_SQLITE to table

README.md
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-06-05 13:41:26 -04:00
jason cce3b4528d 🐛 Fix sqlite DATABASE_DIR path; 📝 rewrite README 🐛
DATABASE_DIR fix (08-gitea.sh):
DATABASE_SERVICE_TYPE="sqlite" triggers a generic block that appends
/$SERVER_NAME to /data/db/sqlite. Before the SERVER_NAME fix that was
empty giving /data/db/sqlite//gitea.db; even after it would be
/data/db/sqlite/<hostname> not under DATA_DIR. Re-pin DATABASE_DIR to
$DATA_DIR/db/sqlite after the generic block.
README rewrite:
- Full env var reference table (GITEA_SERVER, GITEA_PROTO, GITEA_NAME,
GITEA_ADMIN, GITEA_EMAIL_*, GITEA_SQL_*, ACT_RUNNER_FALLBACK_VERSION,
RUNNERS_START, DOMAIN, DEBUGGER)
- Volume and port tables
- Production notes: --privileged required, GITEA_SERVER must be set,
mailer disabled by default, DNS override explained
- Canonical section order: Docker → Development → License
- README.md: full rewrite with env vars, volumes, ports, and production notes
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: fix DATABASE_DIR to always use $DATA_DIR/db/sqlite

README.md
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-06-05 13:20:18 -04:00
jason bd301103c4 🐛 Fix REPLACE_* token substitution in config files 🐛
Two substitution bugs fixed:
act_runner (zz-act_runner.sh):
- REPLACE_RUNNER_* tokens were only substituted inside the registration
block (guarded by SYS_AUTH_TOKEN + runners file absence). If gitea
wasn't ready on first boot, the file was copied with tokens intact
and never substituted on subsequent boots.
- Fix: substitute tokens immediately after copy, unconditionally.
Registration logic remains gated on auth token availability.
gitea app.ini (08-gitea.sh):
- REPLACE_SERVER_NAME and REPLACE_SERVER_PROTO had no matching env
vars — the script used HOSTNAME and SERVICE_PROTOCOL instead, so
__initialize_replace_variables left those tokens unsubstituted.
- Fix: export SERVER_NAME="${DOMAIN:-$HOSTNAME}" and
SERVER_PROTO="${SERVICE_PROTOCOL:-http}" as aliases after the
HOSTNAME chain is resolved.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: add SERVER_NAME and SERVER_PROTO aliases for token substitution
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: move REPLACE_ substitution outside registration guard

rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-06-05 13:14:39 -04:00
jason 541e3398a0 🐛 Fix container DNS: ship resolv.conf without search domain 🐛
Hosts with a search domain (e.g. search casjay.dev) cause containers
to inherit it. When that zone has a wildcard AAAA record, public
hostnames like github.com resolve to the host's own IPv6 address
instead of the real server, breaking all HTTPS (and any other
protocol) from inside the container.
The entrypoint already has a hook: if /usr/local/etc/resolv.conf
exists it replaces /etc/resolv.conf at container startup. Ship a
clean resolv.conf with Cloudflare + Google DNS and no search domain
so container DNS is always correct regardless of host configuration.
- rootfs/usr/local/etc/resolv.conf: new file — clean DNS, no search domain

rootfs/usr/local/etc/resolv.conf
2026-06-05 12:22:20 -04:00
jason dd8fa3d25c 🐛 Add retry logic to gitea and act_runner downloads 🐛
gitea.com was returning 502 Bad Gateway from the build host, causing
the act_runner download to fail immediately with no retry. Added
--retry 5 --retry-delay 10 --retry-all-errors to both download curl
calls so transient gateway errors don't abort the build.
- rootfs/root/docker/setup/05-custom.sh: add retry flags to gitea and act_runner curl download calls

rootfs/root/docker/setup/05-custom.sh
2026-06-04 17:30:26 -04:00
jason 65c2ec64f6 🐛 Fix act_runner download: repo renamed, new binary names 🐛
The gitea/act_runner repo was renamed to gitea/runner and binary
filenames changed from act_runner-{ver}-linux-{arch} to
gitea-runner-{ver}-linux-{arch} (with version stripping the leading
'v'). The old URLs returned 404 causing every build to fail.
Also adds resilience for builds where gitea.com is unreachable:
- 30s connect timeout / 45s max-time on API calls
- Pinned fallback version (v1.0.8) used when API returns nothing
- Fallback direct URL constructed from version tag without API
- Empty-URL guard before curl invocation prevents blank-argument error
- rootfs/root/docker/setup/05-custom.sh: fix repo path gitea/act_runner → gitea/runner, fix binary name pattern, add fallback version, add fallback URL construction, add empty-URL guard

rootfs/root/docker/setup/05-custom.sh
2026-06-04 17:13:51 -04:00
jason 5349e92de9 🐛 Disable act_runner cache — external_secret required when enabled 🐛
default_config.yaml had cache.enabled=true but no external_secret,
dir, host, or port configured. act_runner refuses to start the cache
server without external_secret, logging an error on every boot.
cache_server.yaml already has cache disabled — align default_config
to match.
- rootfs/tmp/etc/act_runner/default_config.yaml: cache.enabled false

rootfs/tmp/etc/act_runner/default_config.yaml
2026-06-04 16:54:06 -04:00
jason ab8d2b9ffc ♻️ Migrate gitea to /config/ source-of-truth architecture ♻️
Migrate gitea Docker image to the new build-time config architecture.
- rootfs/root/docker/setup/03-files.sh: rewrite to canonical form with /tmp/bin, /tmp/var, /tmp/etc, /tmp/usr handlers; remove template-files copy block
- rootfs/usr/local/etc/docker/functions/entrypoint.sh: update to latest template with __init_service_conf, __find_php_ini, __find_php_bin helpers
- rootfs/usr/local/etc/docker/init.d/*.sh: fix $(basename) UUOC → ${var##*/}; move inline comments above code lines; remove commented-out dead code
- rootfs/usr/local/share/template-files/: delete entire directory; config files now deployed via /tmp/etc/ at build time

rootfs/root/docker/setup/03-files.sh
rootfs/usr/local/etc/docker/functions/entrypoint.sh
rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
rootfs/usr/local/share/template-files/config/env/default.sample
rootfs/usr/local/share/template-files/config/env/examples/00-directory.sh
rootfs/usr/local/share/template-files/config/env/examples/addresses.sh
rootfs/usr/local/share/template-files/config/env/examples/certbot.sh
rootfs/usr/local/share/template-files/config/env/examples/couchdb.sh
rootfs/usr/local/share/template-files/config/env/examples/dockerd.sh
rootfs/usr/local/share/template-files/config/env/examples/global.sh
rootfs/usr/local/share/template-files/config/env/examples/healthcheck.sh
rootfs/usr/local/share/template-files/config/env/examples/mariadb.sh
rootfs/usr/local/share/template-files/config/env/examples/mongodb.sh
rootfs/usr/local/share/template-files/config/env/examples/networking.sh
rootfs/usr/local/share/template-files/config/env/examples/other.sh
rootfs/usr/local/share/template-files/config/env/examples/php.sh
rootfs/usr/local/share/template-files/config/env/examples/postgres.sh
rootfs/usr/local/share/template-files/config/env/examples/redis.sh
rootfs/usr/local/share/template-files/config/env/examples/services.sh
rootfs/usr/local/share/template-files/config/env/examples/ssl.sh
rootfs/usr/local/share/template-files/config/env/examples/supabase.sh
rootfs/usr/local/share/template-files/config/env/examples/webservers.sh
rootfs/usr/local/share/template-files/config/env/examples/zz-entrypoint.sh
rootfs/usr/local/share/template-files/config/.gitkeep
rootfs/usr/local/share/template-files/data/.gitkeep
rootfs/usr/local/share/template-files/defaults/.gitkeep
2026-06-04 14:41:57 -04:00
jason 98640213a2 🐛 Fall back to hostname -f for GITEA_SERVER when unset 🐛
HOSTNAME resolution now tries hostname -f (FQDN) before falling back
to the short $HOSTNAME, giving a usable ROOT_URL out of the box on
hosts where the FQDN is set in /etc/hosts or DNS.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: HOSTNAME fallback
chain: GITEA_SERVER → GITEA_HOSTNAME → FULL_DOMAIN_NAME →
hostname -f → $HOSTNAME

rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-05-31 15:36:55 -04:00
jason 7cc09e7cfc 🐛 Fix persistent deprecated settings and ROOT_URL mismatch 🐛
Two issues with existing persistent volumes:
1. Deprecated app.ini settings ([cors].X_FRAME_OPTIONS,
[picture].DISABLE_GRAVATAR, [picture].ENABLE_FEDERATED_AVATAR) were
baked into the volume config from the old template and never removed
on subsequent container starts.
2. ROOT_URL/DOMAIN/SSH_DOMAIN were substituted once on first run from
the container hostname and never updated when GITEA_SERVER/GITEA_PROTO
env vars changed, causing the "Mismatched ROOT_URL" warning.
Fix: add migration + dynamic resync in __update_conf_files (08-gitea.sh)
that runs on every startup against both the persistent (/config/gitea)
and runtime (/etc/gitea) copies of app.ini, so changes take effect
immediately without a second restart.
Set GITEA_PROTO=https and GITEA_SERVER=git.casjay.work to populate
the correct ROOT_URL at container start.
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: add dynamic ROOT_URL
resync and deprecated-setting removal to __update_conf_files

rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-05-31 15:34:40 -04:00
jason a3296f475f 🐛 Fix SSL errors for repository migrations 🐛
SSL interception on this network presents certificates without SANs
for the target hostname, breaking git clone operations during Gitea
migrations. Add migration and git-level TLS bypass settings.
- rootfs/tmp/etc/gitea/app.ini: add [migration] section with SKIP_TLS_VERIFY=true
- rootfs/tmp/etc/gitea/app.ini: add [git.config] http.sslVerify=false

rootfs/tmp/etc/gitea/app.ini
2026-05-31 15:25:56 -04:00
jason 0abc43bffc 🐛 Fix act_runner registration order 🐛
Runners were launched in parallel subshells with only a 2-second gap
between them. act_runner register is a network call; if Gitea was
still warming up any registration could race past an earlier one,
causing Gitea to assign IDs out of sequence (1,3,2,5,4 instead of
1,2,3,4,5).
Split into two phases: register all runners sequentially first so IDs
are assigned in the correct order, then launch all daemons in parallel
once every runner is confirmed registered.
- rootfs/usr/local/bin/start-runners: split __start_runner into
__register_runner (sequential, phase 1) and __start_runner_daemon
(parallel, phase 2); remove the sleep 2 workaround

rootfs/usr/local/bin/start-runners
2026-05-24 21:37:50 -04:00
jason 755b3db301 🐛 Fix all Gitea v1.26 deprecated config settings 🐛
Resolve all deprecation warnings emitted at runtime by updating
app.ini to use current key names and locations.
- rootfs/tmp/etc/gitea/app.ini: move X_FRAME_OPTIONS from [cors] to [security] (deprecatedSetting v1.26.0)
- rootfs/tmp/etc/gitea/app.ini: remove [picture].DISABLE_GRAVATAR (deprecatedSettingDB since v1.18, use admin panel)
- rootfs/tmp/etc/gitea/app.ini: remove [picture].ENABLE_FEDERATED_AVATAR (deprecatedSettingDB since v1.18, use admin panel)
- rootfs/tmp/etc/gitea/app.ini: rename [lfs].LFS_CONTENT_PATH → PATH (was silently ignored; correct key is PATH)
- rootfs/tmp/etc/gitea/app.ini: rename [git].MAX_GIT_DIFF_LINE_CHARACTER_COUNT → MAX_GIT_DIFF_LINE_CHARACTERS (correct struct field name)
- rootfs/tmp/etc/gitea/app.ini: remove LOG_ROTATE/DAILY_ROTATE/MAX_DAYS from [log] root section (only valid in file-writer sub-sections; dead config with MODE=console)

.claude/settings.local.json
rootfs/tmp/etc/gitea/app.ini
2026-05-24 21:18:57 -04:00
jason ae8a7583a8 🔧 Harden gitea binary download in 05-custom.sh 🔧
Fix SSL and rate-limit failures when downloading gitea during docker build.
The GitHub REST API is rate-limited at 60 req/hour for unauthenticated
requests from Docker BuildKit's outgoing IP. Additionally, BuildKit resolves
github.com via the host DNS which may return an IPv6 address served by a
transparent proxy, causing TLS cert verification failures (error 60: "no
alternative certificate subject name matches target hostname 'github.com'").
Changes:
- rootfs/root/docker/setup/05-custom.sh: replace JSON API version lookup
with a redirect-follow approach (curl -4sfL -o /dev/null -w %{url_effective})
that avoids the rate-limited /releases/latest API endpoint entirely
- rootfs/root/docker/setup/05-custom.sh: add -4 (IPv4-only) flag to all
github.com curl calls to bypass intercepted IPv6 DNS resolutions
- rootfs/root/docker/setup/05-custom.sh: add explicit ca-certificates
install and update-ca-certificates before any HTTPS downloads, since
the base image cert bundle may be stale after system upgrade

rootfs/root/docker/setup/05-custom.sh
2026-05-24 20:53:40 -04:00
jason 7668154e67 🐛 Fix silent download failure and cosmetic naming bugs 🐛
Fixes three bugs discovered during live container testing.
The critical bug was a bash post-increment no-op: `exitCode=$((exitCode++))`
assigns the *old* value back to the variable, so exitCode stays 0 even
when a download fails. This caused the Docker build to succeed silently
when the gitea binary download failed, publishing a broken image to Docker Hub.
- rootfs/root/docker/setup/05-custom.sh: change exitCode=$((exitCode++)) to
exitCode=$((exitCode + 1)) in both the gitea and act_runner failure handlers
- rootfs/usr/local/bin/entrypoint.sh: change CONTAINER_NAME and description
from "archlinux" (copied template default) to "gitea"
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: remove leading space from
[ -d " /config/ssh" ] path test so the directory existence check is correct

.claude/
rootfs/root/docker/setup/05-custom.sh
rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2026-05-24 19:58:15 -04:00
jason 895520eb77 🐛 Fix runner config filenames, cache-server, and registration log 🐛
Three more bugs found during full component verification:
1. RUNNER_CONFIG_DEFAULT pointed to config.yaml but the actual
template filename is default_config.yaml — gitea named runner
never registered because the file-existence check always failed.
2. CACHE_CONFIG_FILE pointed to cache.yaml but the actual template
filename is cache_server.yaml — cache-server launch always
skipped silently.
3. act_runner v1.0.6 requires cache.external_secret on both the
cache-server and any runner using external_server; neither config
had it, so cache-server exited immediately and runner registration
failed when external_server was present in default_config.yaml.
4. Registration log redirect was 2>/dev/stdout >>"$log" (stderr went
to original stdout, not the log); corrected to >>"$log" 2>&1.
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh:
- RUNNER_CONFIG_DEFAULT: config.yaml → default_config.yaml
- CACHE_CONFIG_FILE: cache.yaml → cache_server.yaml
- fix registration log redirect: >>"$RUNNER_LOG_FILE" 2>&1
- rootfs/tmp/etc/act_runner/default_config.yaml: remove
external_server (no shared secret configured; each runner uses
its own internal cache)
- rootfs/tmp/etc/act_runner/cache_server.yaml: set enabled: false
(cache-server requires external_secret; disabled until a proper
shared-secret setup is added)
Verified: 6 daemons on fresh start (1 gitea named + 5 runners), all
with 22 labels; clean reconnect on restart with no re-registration.

rootfs/tmp/etc/act_runner/cache_server.yaml
rootfs/tmp/etc/act_runner/default_config.yaml
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-05-24 15:16:16 -04:00
jason e8021e29e2 🐛 Fix act_runner token generation and gitea auto-install 🐛
Runner registration was broken by three compounding bugs:
1. Token generated at script init time (before gitea was ready)
2. gitea CLI missing --work-path/--custom-path flags, writing fatal
log messages to stdout which got captured as the token value
3. Token assignment inside a piped subshell didn't propagate back
to the parent shell, leaving SYS_AUTH_TOKEN empty at runtime
4. INSTALL_LOCK=false in app.ini template caused gitea to start in
install-wizard mode, making generate-runner-token always fail
- rootfs/tmp/etc/gitea/app.ini: set INSTALL_LOCK=true so gitea
auto-initializes the SQLite DB on first run
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh:
- defer SYS_AUTH_TOKEN: initialize to empty at global scope,
generate in __run_pre_execute_checks after gitea is confirmed up
- add --work-path/--custom-path to gitea CLI call; filter output
with grep -oE '[A-Za-z0-9]{20,}' to extract only the token
- guard token generation on INSTALL_LOCK=true in app.ini
- read token back from $CONF_DIR/tokens/system after the piped
__run_pre_execute_checks call returns (subshell escape)
Tested: fresh start registers all 5 runners with full 22-label set;
restart skips re-registration and reconnects all 5 daemons cleanly.

rootfs/tmp/etc/gitea/app.ini
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-05-24 14:11:11 -04:00
jason 3a21cd6091 🐛 Fix generated start script: empty su_exec produces '' command prefix 🐛
When su_exec is empty (service runs as root, no user-switching needed),
printf '%q ' $su_exec expands to the literal string '' which gets embedded
in the generated start script as a command prefix, causing bash to try
executing a program named '' and failing immediately. Also add explicit
PATH and HOME exports to the RESET_ENV=no generated script so services
are not dependent on environment inheritance.
- rootfs/usr/local/etc/docker/init.d/05-dockerd.sh: fix _q_su assignment
in both RESET_ENV branches to use ${su_exec:+...} so it's empty string
(not '') when su_exec is empty; fix format string %s%s (no space between
su and cmd, su already carries trailing space); add PATH and HOME exports
to RESET_ENV=no generated script
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: same fixes
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: same fixes

rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-05-24 13:00:24 -04:00
jason e599f1edc8 🐛 Fix start-runners: wrong --config arg kept all runners permanently offline 🐛
The daemon was called with --config pointing at the .runner registration
state file (JSON), not a YAML config. act_runner rejected it immediately
on every start, so all runners were always offline and never reconnected.
Also fix log truncation and stale fallback labels.
- rootfs/usr/local/bin/start-runners: remove --config from act_runner
daemon invocation (act_runner finds .runner in CWD automatically after
cd "$runner_dir"); fix __log to append (>>) instead of truncate (>);
update fallback RUNNER_LABELS to match the full label set defined in
zz-act_runner.sh

rootfs/usr/local/bin/start-runners
2026-05-24 12:32:25 -04:00
jason 1f84972d9d 🗑️ Remove scaffolding template 00-server01.sh 🗑️
Was added as a reference artifact during framework migration work
and should not live in the repo.
- rootfs/usr/local/etc/docker/init.d/00-server01.sh: deleted

rootfs/usr/local/etc/docker/init.d/00-server01.sh
2026-05-24 12:24:36 -04:00
jason d74ff680d2 🐛 Fix undefined variables and ordering bugs in act_runner init script 🐛
Fix all undefined variable references and logic errors that would
prevent runner registration and daemon startup from working.
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: fix GITEA_USER
typo (missing $ before SERVICE_USER); define 9 previously undefined
variables: RUNNER_IP_ADDRESS, RUNNER_CONFIG_DEFAULT, RUNNER_DEFAULT_HOME,
RUNNER_CONFIG_NAME, RUNNER_LOG_FILE, RUNNER_DAEMON_LOG, RUNNER_CACHE_HOST,
CACHE_CONFIG_FILE, CACHE_LOG_FILE; swap ctime/waitTime local declarations
so ctime is defined before waitTime uses it; quote act_runner daemon and
cache-server --config paths

rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2026-05-24 12:23:38 -04:00
jason 4d51cc0e7c 🔧 Sync template framework updates and fix app.ini config 🔧
Bring all init scripts and support files up to the latest docker
template framework, and fully configure gitea's app.ini for a
performant, open, reverse-proxy-aware deployment.
- rootfs/tmp/etc/gitea/app.ini: add missing sections ([server],
[cache], [queue], [git], [git.timeout], [api], [webhook],
[indexer], [session], [oauth2], [metrics], [repository.release]);
raise MAX_RESPONSE_ITEMS=500; set PROTOCOL=http, HTTP_ADDR=0.0.0.0,
USE_PROXY_PROTOCOL=false; INSTALL_LOCK=false; tune DB/session/security
- rootfs/usr/local/bin/entrypoint.sh: direct template sync — new trap
style, SSL_CA fix, ENTRYPOINT_PID_FILE path, mapfile, __netstat call
- rootfs/usr/local/etc/docker/functions/entrypoint.sh: direct template
sync — add __log_debug/info/warn/error; improve __netstat, __mkdir,
__rm, __grep_test (639 changed lines)
- rootfs/usr/local/etc/docker/init.d/00-server01.sh: new generic
template/example init.d service script
- rootfs/usr/local/etc/docker/init.d/05-dockerd.sh: framework update —
__trap_err_handler ERR handler, SIGPWR split, enabled-check expanded,
debug if/else, env loop guard, $(<...) PID read, __check_service guard,
__run_start_script rewrite (printf %q, md5sum hash, bash launcher),
errorCode=${PIPESTATUS[0]}, remove unconditional SERVICE_EXIT_CODE=0,
fix __post_execute fire-and-forget
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: same framework updates
as 05-dockerd.sh, service-specific content preserved
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: same framework
updates; service-specific __post_execute daemon/cache-server logic kept
- rootfs/root/docker/setup/00-init.sh: version stamp sync
- rootfs/root/docker/setup/01-system.sh: version stamp sync
- rootfs/root/docker/setup/02-packages.sh: version stamp sync
- rootfs/root/docker/setup/03-files.sh: header-only patch, gitea-specific
body preserved
- rootfs/root/docker/setup/04-users.sh: version stamp sync
- rootfs/root/docker/setup/05-custom.sh: header-only patch, gitea/act_runner
binary download logic preserved
- rootfs/root/docker/setup/06-post.sh: version stamp sync
- rootfs/root/docker/setup/07-cleanup.sh: version stamp sync
- rootfs/usr/local/share/template-files/config/env/default.sample:
ENTRYPOINT_PID_FILE path → /run/init.d/entrypoint.pid
- rootfs/usr/local/share/template-files/config/env/examples/zz-entrypoint.sh:
ENTRYPOINT_PID_FILE path → /run/init.d/entrypoint.pid

rootfs/root/docker/setup/00-init.sh
rootfs/root/docker/setup/01-system.sh
rootfs/root/docker/setup/02-packages.sh
rootfs/root/docker/setup/03-files.sh
rootfs/root/docker/setup/04-users.sh
rootfs/root/docker/setup/05-custom.sh
rootfs/root/docker/setup/06-post.sh
rootfs/root/docker/setup/07-cleanup.sh
rootfs/tmp/etc/gitea/app.ini
rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/etc/docker/functions/entrypoint.sh
rootfs/usr/local/etc/docker/init.d/00-server01.sh
rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
rootfs/usr/local/share/template-files/config/env/default.sample
rootfs/usr/local/share/template-files/config/env/examples/zz-entrypoint.sh
2026-05-24 12:19:59 -04:00
jason 4fc5a83354 🗃️ Removed the .claude/settings.local.json 🗃️
Dockerfile
.env.scripts
.gitattributes
.gitea/workflows/docker.yaml
.gitignore
LICENSE.md
README.md
rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/bin/pkmgr
2026-05-12 20:06:34 -04:00
jason 8f8cb303f9 🗃️ rootfs: shield internal entrypoint PID files from /run/*.pid sweeps 🗃️
Update the embedded entrypoint copies in rootfs/ to match the
upstream template change. Internal state files renamed to dotfiles
so they're not matched by `/run/*.pid` cleanup globs:
- /run/init.d/entrypoint.pid -> /run/.entrypoint.pid
- /run/no_exit.pid -> /run/.no_exit.pid
- /run/backup.pid -> /run/.backup.pid
- /run/__start_init_scripts.pid -> /run/.start_init_scripts.pid
Per-service PIDs in /run/init.d/ are unchanged.

rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/etc/docker/functions/entrypoint.sh
rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
rootfs/usr/local/share/template-files/config/env/default.sample
rootfs/usr/local/share/template-files/config/env/examples/zz-entrypoint.sh
2026-05-05 19:11:44 -04:00
jason 3c8cdd11fe 🗃️ Update codebase 🗃️
rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/etc/docker/functions/entrypoint.sh
2025-11-30 16:25:31 -05:00
jason e8ff6f5b08 🐳 Enhancement: Entrypoint Script Modifications for Docker Containers 🐳
rootfs/usr/local/etc/docker/functions/entrypoint.sh
2025-11-30 16:01:56 -05:00
jason b9d56bbcb9 🗃️ Update codebase 🗃️
rootfs/tmp/etc/docker/daemon.json
rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
2025-11-29 16:01:40 -05:00
jason 63d18bb750 🔧 Update configuration files 🔧
.claude/
Dockerfile
.env.scripts
rootfs/tmp/etc/docker/daemon.json
rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/etc/docker/init.d/05-dockerd.sh
2025-11-29 15:48:20 -05:00
jason a46ba76ca9 🗃️ Update codebase 🗃️
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2025-11-29 15:21:51 -05:00
jason 265f823955 🗃️ Update codebase 🗃️
rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh
2025-11-29 14:41:59 -05:00
jason ef6d219131 🗃️ Update codebase 🗃️
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2025-11-29 14:30:40 -05:00
jason 3abf0704ee 🗃️ Update codebase 🗃️
rootfs/usr/local/etc/docker/init.d/08-gitea.sh
2025-11-29 13:32:03 -05:00