Self-hosted Gitea,
managed from one binary.
Install, upgrade, and configure Gitea and the Runner — HTTPS, declarative config, backup, and self-update. One verifiable binary, no runtime to babysit.
$ curl -fsSL https://dl.gtcnsl.com/latest/gtcnsl-v1.3.2-linux-amd64 -o /usr/local/bin/gtcnsl && chmod +x /usr/local/bin/gtcnsl
What it does
The whole Gitea lifecycle, declarative and verifiable.
Verified install & upgrade
Pulls Gitea from the official mirror with GPG and SHA-256 verification, and the Runner with SHA-256; detects an existing install and upgrades it safely in place.
HTTPS profiles & adopt
Direct HTTPS via built-in ACME or your own certificate, with automatic rollback. gitea adopt brings a hand-rolled install under management without moving data.
Declarative app.ini
Keep desired state in Git. gtcnsl config apply reconciles the server — with a diff and a backup first. config get/set/toggle for one-off changes.
Secret management
Generate, rotate, and store Gitea secrets safely — including a guarded SECRET_KEY rotation that re-encrypts every affected row instead of orphaning it.
Backup, restore & self-update
Snapshots Gitea binary and config for restore, manages the gitea and gitea-runner systemd units, and keeps gtcnsl itself current with self-update — every step rolls back on failure.
TUI and CLI
Interactive TUI by default; a non-interactive CLI for cron and CI pipelines — the same static binary for linux amd64, arm64, and armv7.
A console, not a script
Launch gtcnsl with no arguments and you get a real terminal UI — services, config presence, and secrets at a glance.
Quickstart
Zero to a running Gitea with CI — three commands.
gtcnsl gitea install --yes
Installs Gitea, generates secrets, writes app.ini, deploys the systemd unit, and starts it — rolled back automatically if the health check fails.
gtcnsl runner install --executor=docker --yes
Installs the Runner and its gitea-runner unit with the Docker executor. It stays stopped until you register it.
gtcnsl runner register --instance https://git.example.com --token <fresh-token> --yes
Registers the runner with your instance and starts it. Grab a token from Site Admin, Runners, Create new runner.
Declarative by default
Keep app.ini as a template in Git. gtcnsl config apply renders it with --var overrides, shows a diff, backs up the old file, then restarts Gitea with a health check.
[server]PROTOCOL = httpHTTP_PORT = 3000SSH_PORT = ${SSH_PORT}DOMAIN = localhostROOT_URL = http://localhost:3000/APP_DATA_PATH = /var/lib/gitea/data[actions]ENABLED = ${ACTIONS_ENABLED}
$ gtcnsl config apply --template /root/app.ini.tmpl --var SSH_PORT=2222 --var ACTIONS_ENABLED=true --yes==> render templatetemplate /root/app.ini.tmpl (681 bytes), 2 variable(s)done in 0s==> parse currentdone in 0s==> diff2 change(s):[actions] ENABLED: "true" (added)[server] SSH_PORT: "22" → "2222" (changed)done in 0s==> applybackup written to /etc/gitea/app.ini.bakdone in 9ms==> restart + health checkgitea.service restartedGitea is responding againdone in 1.019sapplied 2 change(s) to /etc/gitea/app.ini
Runs where you run
One binary across the distros and architectures you actually deploy.
Why a binary, not a script
Built for people who treat their server like production.
One static binary
No Python, no Ansible, no runtime to install or version. Drop it on the box and run.
Verifiable
Gitea downloads are checked against GPG signatures and SHA-256; the Runner and gtcnsl itself are checked by SHA-256 — every time, before anything touches your system.
Idempotent
Declarative state means re-running is safe. Apply the same config twice, get the same server.
Whole lifecycle
Install, upgrade, configure, and run — one tool instead of a folder of fragile shell scripts.
Status
v1.x — the CLI is stable and SemVer-versioned since v1.0.
Questions
Only what your declarative config covers. Everything else is left alone, and config apply shows a diff and writes a backup before any change.
Yes. gtcnsl gitea adopt brings a hand-rolled install under management without moving data (dry-run by default), then config apply reconciles app.ini against your template with a diff and a backup first.
For installs and service operations, yes — it manages systemd units. Read-only commands like doctor and config get do not.
No. No account, no telemetry, no phone-home. One binary and your server.
Gitea binaries are checked against their GPG signature and SHA-256; the Runner and gtcnsl self-update are checked by SHA-256 — every download, every time.