GITEA_HOSTNAME was doing double duty: a bare hostname for the
start_pre() MagicDNS getent check, and (implicitly, via manual
instructions) a base for the registration URL. Since Gitea moved to
`tailscale serve --https=443` (#19), the instance is reachable on 443
with no port — the old implicit `http://<hostname>:3000` no longer
applies.
GITEA_HOSTNAME stays a bare hostname; GITEA_INSTANCE_URL is a new,
independently overridable variable defaulting to
https://${GITEA_HOSTNAME}, forwarded through exec_in_lxc and used in
the printed registration command.
The instance URL is frozen into .runner at registration time, so
changing the variable doesn't retroactively fix an already-registered
runner. check_runner_url_drift() detects a mismatch and warns with
the re-registration procedure, without touching .runner — deleting a
working runner's registration is a deliberate, manual, documented
step, not something a rerunnable install script should do on its own.
Closes#22
openbao: removed its now-duplicate ensure_template_present() definition,
using the one factored into lib/common.sh (call site unchanged).
gitea-runner: replaced its ad-hoc template-download check (which skipped
`pveam update`, risking a stale cached template list now that the template
is auto-detected) with a call to the shared ensure_template_present().
Also added ca-certificates to exec_in_lxc's apk add, matching openbao, and
added require_root() to the inside-LXC dispatch path in main(), which
openbao already does but gitea-runner was missing.
source <(curl ...) swallows curl failures (404, network error): an empty
stream still makes `source` return 0, so the failure would otherwise only
surface later as a confusing "command not found" for one of lib/common.sh's
functions. Check that a known function landed after the source, and exit 1
with the attempted URL if not.
Was a fixed value, unlike openbao's SCRIPT_URL="${SCRIPT_URL:-...}". Two
consequences: exec_in_lxc forwarded SCRIPT_URL into the container where it
was immediately overwritten by the hardcoded value, making the forward a
no-op; and the lib/common.sh sourcing fallback derives its fetch URL from
SCRIPT_URL, so it always pointed at main (where lib/common.sh doesn't exist
yet), making this branch untestable end-to-end for gitea-runner.
log_info() etc. wrote to stdout, unlike openbao's identical functions
which write to stderr specifically so $(fn) capture is safe. lib/common.sh's
detect_latest_alpine_template() does `log_info "Selected..."; echo "$tmpl"` —
in gitea-runner, TEMPLATE=$(detect_latest_alpine_template) therefore captured
the log line and ANSI codes along with the template name, breaking both the
pveam list lookup and pct create's template argument.
Ports openbao's host-side update path to gitea-runner: main() now uses
find_existing_lxc (hostname/tag match) to switch into a new update_lxc()
instead of always recreating the container, with an explicit --update
dispatch case reaching update_runner() (previously inferred only from
/usr/local/bin/act_runner presence). require_root is ported from openbao
for the host-side pct branch.
Extracted a small exec_in_lxc() helper (option a from the two offered)
rather than duplicating the curl-pipe invocation, since main() now needs
to drive both the create and update paths through the same piping logic
with only the trailing --install/--update flag differing — matching
openbao's own exec_in_lxc for consistency.
update_runner() now calls refresh_os_packages before touching the binary,
mirroring openbao's update_inside_lxc(). Also switched create_lxc's LXC
tag from the hardcoded "cicd" to the LXC_TAG variable (added in the prior
commit but unused until now) so find_existing_lxc's tag match actually
works.
Documented the OS-refresh-on-update behavior in both READMEs.
Closes#15
Both install scripts now source lib/common.sh instead of duplicating
detect_latest_alpine_template(), find_existing_lxc(), and the tty1
autologin block. Since these scripts are distributed via curl one-liner
and piped into `pct exec` inside the LXC, there is no local checkout to
source from in those contexts — lib/common.sh is sourced from disk when
a local checkout is available (BASH_SOURCE resolves to a real path),
otherwise fetched over HTTP next to SCRIPT_URL. Both scripts already
require outbound network to curl themselves and to download their
respective binaries, so this adds no new failure mode.
openbao/install.sh is a behavioral no-op: same log output, same control
flow. One inline apk update/upgrade is intentionally left as-is in
update_lxc() — refresh_os_packages() is a bash function in this
process and can't run over `pct exec ... sh -c` without shipping the
function definition into the container.
gitea-runner/install.sh fixes the actual bug: TEMPLATE was hardcoded to
a specific dated Alpine release, so create_lxc() would keep trying to
provision a stale/absent template. TEMPLATE now defaults to empty and
create_lxc() calls detect_latest_alpine_template() when unset, mirroring
openbao. Also renamed HOSTNAME -> HOSTNAME_LXC and added LXC_TAG to
match openbao's naming, since a follow-up (issue #15) will wire up
find_existing_lxc()-based update detection here.
Closes#12, Closes#14
Remplace le hostname Tailscale hardcodé par la variable GITEA_HOSTNAME
(défaut: gitea.taila5ad8.ts.net), cohérent avec GITEA_API et VERSION_FILE.
Le heredoc étant single-quoted (<<'EOF'), la valeur est injectée à
l'écriture du service via sed, évitant tout conflit avec les variables
OpenRC runtime ($PATH, ${RC_SVCNAME}, etc.).
OpenRC's `tailscale [started]` dependency only guarantees the tailscaled
process is up, not that MagicDNS is operational. At boot this creates a
race condition where act_runner starts before gitea.taila5ad8.ts.net is
resolvable, causing the runner to fail to connect to Gitea.
Add an active DNS poll in start_pre() using getent, with a 30-second
timeout and an explicit eerror on expiry. depend() is unchanged.
Port the working autologin block from openbao/install.sh so both Proxmox
installers behave identically. The previous version assumed agetty was
already installed and relied on a sed pattern that no-ops on fresh Alpine
images; it also never told PID 1 to re-read /etc/inittab, so the change
required a reboot.
- Install agetty (with util-linux fallback) via apk.
- Drop any existing tty1 line and append the autologin line (robust
against inittab layout drift across Alpine releases).
- SIGHUP PID 1 and kill any stale getty so init respawns the new line
immediately — no reboot needed, no first-login "type exit once" wart.
- Add Tailscale installation and service start in install.sh
- Update service dependencies to include tailscale
- Add instructions to connect via Tailscale after installation
The script now uses the ip command instead of hostname -i to reliably
obtain the container's IPv4 address. Service command output is also
redirected to /dev/null to reduce noise in the logs.