Add webapp: Next.js LXC with deploy-as-code via Gitea Actions runner #1

Merged
l.kirchner merged 3 commits from add-webapp into main 2026-06-05 02:33:38 +02:00
Owner

New webapp script following the two-file convention (ct/ + install/, sourcing the shared libs).

What it does

Creates an unprivileged Debian 12 LXC that serves a Next.js site and redeploys itself on every push, using a self-hosted Gitea Actions runner in host mode (deploy-as-code) instead of a webhook.

  • ct/webapp.sh — host side: creates the LXC (4 GB RAM, 30 GB disk), prompts for the Gitea instance URL, a runner registration token and the NEXT_PUBLIC_* values, pushes them into the container and bootstraps the installer. All env-overridable for non-interactive use.
  • install/webapp-install.sh — in-container: installs Node.js (NodeSource) + git/rsync/sudo, downloads & registers act_runner (host mode, runs as the unprivileged webapp user, polls Gitea outbound — no inbound port), writes /etc/webapp/env, and sets up two systemd units (webapp.service for next start, webapp-runner.service for the runner). A narrow sudoers rule lets the runner restart only webapp.service.
  • README.md — adds the webapp row to the scripts table.

The build/deploy logic itself lives in the website repo's .gitea/workflows/deploy.yml (separate PR in l.kirchner/Redesign-ad2b).

Design notes

  • No read token and no inbound port: the runner authenticates outbound; actions/checkout uses the per-job token.
  • Runner and service share the webapp user, so the workflow syncs into the live copy without privileges; only systemctl restart webapp.service is sudo-allowed.
  • NEXT_PUBLIC_* stay in /etc/webapp/env (sourced at build time) so the repo carries no environment-specific config.
  • act_runner pinned to 0.2.13, overridable via RUNNER_VERSION.

Validation

shellcheck clean (only the same SC2034/SC1090 as devpi.sh, from the curl-sourced libs), bash -n passes, sudoers format checked, workflow YAML parses.

Prerequisites (deploy time)

Actions enabled on the instance and the repo; a runner registration token; outbound HTTPS to the Gitea instance and to github.com (for actions/checkout).

New `webapp` script following the two-file convention (`ct/` + `install/`, sourcing the shared libs). ## What it does Creates an unprivileged Debian 12 LXC that serves a Next.js site and redeploys itself on every push, using a self-hosted **Gitea Actions runner in host mode** (deploy-as-code) instead of a webhook. - `ct/webapp.sh` — host side: creates the LXC (4 GB RAM, 30 GB disk), prompts for the Gitea instance URL, a **runner registration token** and the `NEXT_PUBLIC_*` values, pushes them into the container and bootstraps the installer. All env-overridable for non-interactive use. - `install/webapp-install.sh` — in-container: installs Node.js (NodeSource) + `git`/`rsync`/`sudo`, downloads & registers `act_runner` (host mode, runs as the unprivileged `webapp` user, polls Gitea outbound — no inbound port), writes `/etc/webapp/env`, and sets up two systemd units (`webapp.service` for `next start`, `webapp-runner.service` for the runner). A narrow sudoers rule lets the runner restart **only** `webapp.service`. - `README.md` — adds the `webapp` row to the scripts table. The build/deploy logic itself lives in the website repo's `.gitea/workflows/deploy.yml` (separate PR in `l.kirchner/Redesign-ad2b`). ## Design notes - No read token and no inbound port: the runner authenticates outbound; `actions/checkout` uses the per-job token. - Runner and service share the `webapp` user, so the workflow syncs into the live copy without privileges; only `systemctl restart webapp.service` is sudo-allowed. - `NEXT_PUBLIC_*` stay in `/etc/webapp/env` (sourced at build time) so the repo carries no environment-specific config. - `act_runner` pinned to 0.2.13, overridable via `RUNNER_VERSION`. ## Validation `shellcheck` clean (only the same `SC2034`/`SC1090` as `devpi.sh`, from the curl-sourced libs), `bash -n` passes, sudoers format checked, workflow YAML parses. ## Prerequisites (deploy time) Actions enabled on the instance and the repo; a runner registration token; outbound HTTPS to the Gitea instance and to github.com (for `actions/checkout`).
l.kirchner added 3 commits 2026-06-05 02:31:32 +02:00
Host-side script that creates an unprivileged Debian 12 LXC, installs
Node.js + act_runner in host mode, and registers it against the Gitea
instance. Deploy logic lives in the repo's .gitea/workflows/deploy.yml
(deploy-as-code); the runner polls outbound, so no inbound port.
Installs Node.js and act_runner in host mode, registers the runner as
the unprivileged webapp user, and wires up systemd units for the runner
and the next-start service. A narrow sudoers rule lets the runner restart
only webapp.service; the build/deploy itself is driven by the repo workflow.
l.kirchner merged commit 1d6a15c962 into main 2026-06-05 02:33:38 +02:00
l.kirchner deleted branch add-webapp 2026-06-05 02:33:38 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: luki-net/proxmox-scripts#1