- Rust 69.5%
- Vue 10.4%
- Go 8.5%
- Shell 4.6%
- Python 4.5%
- Other 2.5%
| .cargo | ||
| agent-go | ||
| anleitungen | ||
| ansible | ||
| crates | ||
| docker | ||
| docs | ||
| frontend | ||
| LICENSES | ||
| logo | ||
| scripts | ||
| sources | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| bootstrap-dev.sh | ||
| bootstrap-release.sh | ||
| Cargo.lock | ||
| Cargo.toml | ||
| clean-reset.sh | ||
| deploy.sh | ||
| docker-compose.registry.yml | ||
| docker-compose.yml | ||
| Festplattenbereinigung.sh | ||
| install-deps.sh | ||
| LICENSE | ||
| NOTICE | ||
| README.md | ||
| rebuild.sh | ||
| stop-all.sh | ||
| sync-wiki.sh | ||
| THIRD_PARTY_LICENSES.md | ||
| WRITTEN_OFFER.md | ||
ThinForge Dev
ThinForge brings the golden-image principle from VDI straight to thin-client hardware: one master image, maintained centrally and managed in the browser, is rolled out to the whole fleet via PXE, multicast or BitTorrent and kept current with signed, incremental delta updates.
ThinForge is free software under the GPL-3.0-or-later — see LICENSE and NOTICE. A subscription pays for the hosted VPN service or for unlocking VPN seats, not for the software (see Subscription). Third-party components and their licenses are documented in THIRD_PARTY_LICENSES.md.
Two repositories
| Repository | Purpose |
|---|---|
| ThinForge-Dev (this repository) | Complete source code — the development branch, for reading, building and testing yourself. Versions here are not necessarily fully tested. |
| ThinForge-Release | The tested version for production use: deploy scripts, Compose file, agent binary (every server signs it with its own key), operator documentation. The container images come from the registry. Mirrored to github.com/224ctx/ThinForge. |
For a production installation, use ThinForge-Release:
curl -fsSL https://git.thinforge.org/thinforge/ThinForge-Release/raw/branch/master/bootstrap-release.sh -o bootstrap-release.sh
chmod +x bootstrap-release.sh
./bootstrap-release.sh
- Website: https://thinforge.org
- Operator documentation:
anleitungen/EN/·anleitungen/DE/ - Change log:
docs/CHANGELOG.en.md·docs/CHANGELOG.md(German)
Repository layout
| Path | Purpose |
|---|---|
crates/ |
Rust backend: API, services, worker, migrations, shared data types, Ansible inventory |
frontend/ |
Vue 3 / Vuetify management interface |
agent-go/ |
Go agent that runs on the thin clients |
docker/, docker-compose.yml |
Container stack (dev Compose: builds every ThinForge image locally, including the frontend as a production build — no Vite HMR; third-party images such as PostgreSQL, Redis, Caddy, guacd and NetBird are pulled) |
docker-compose.registry.yml |
Pull-only Compose file for the finished registry images |
rebuild.sh, deploy.sh |
Dev build, or operation from the registry images |
scripts/ |
Tools-ISO provisioning, build helpers, shell libraries, end-to-end test suites (scripts/e2e/) |
ansible/ |
Playbooks (mounted into the backend) |
anleitungen/ |
Operator documentation EN/DE |
sources/, LICENSES/, WRITTEN_OFFER.md |
GPL compliance: source tarballs, license texts, offer for the source |
Building and testing from source
git clone https://git.thinforge.org/thinforge/ThinForge-Dev.git
cd ThinForge-Dev
./rebuild.sh # builds backend, frontend and containers locally (docker compose build)
Alternatively, run the finished registry images against this checkout: ./deploy.sh (uses docker-compose.registry.yml, builds nothing). It pulls the image channel named by THINFORGE_TAG (environment first, then .env, default release); THINFORGE_TAG=beta ./deploy.sh --persist-tag selects the :beta images of the development channel and writes the choice into .env.
The test suites for a running system are described in scripts/e2e/README.md.
rebuild.sh creates .env from .env.example on the first run and generates the secrets (among them POSTGRES_PASSWORD and REDIS_PASSWORD); deploy.sh expects an existing .env. Required variables that an older .env does not know yet — currently REDIS_PASSWORD — are appended with a random value by both scripts via scripts/lib-env.sh (ensure_env_secrets). A docker compose call without this variable aborts with “REDIS_PASSWORD fehlt in .env”.
The Go agent is built in Docker with agent-go/build-and-sign.sh; every installation creates the signature with its own Minisign key, generated during setup. agent-go/bin/ is not under version control: on a fresh checkout, start the stack, run the setup wizard and then agent-go/build-and-sign.sh before the first Tools-ISO build (that is, before the cloning VM is started for the first time) — without a built and signed binary, the backend refuses to build the Tools-ISO.
Next to the binary the script writes agent-go/bin/SOURCE, the source reference of exactly this build: version (the git tag, as in agent-version), source_commit, agent_go_tree (the tree hash of agent-go/), working_tree (clean or modified), built_at, go_image and source_repository. Every commit of this repository for which git rev-parse <commit>:agent-go prints the agent_go_tree value carries the source of that binary; third-party Go modules are pinned in agent-go/go.sum. A binary uploaded or built in the interface replaces the agent without such a reference, and the old SOURCE file is removed.
Outgoing connections
ThinForge works inside your own network. These are all connections that the stack, the agents on the devices, the scripts and the image preparation open towards the outside on their own; traffic between the server and the devices on your network (heartbeat, PXE, NFS, SSH, remote control) is not listed. The operator documentation carries the same list with the menu paths: anleitungen/EN/12-security-and-cve-scan.md.
There is no telemetry, no check with the vendor (the VPN subscription file is verified offline), no check for new ThinForge versions and no ACME/Let's Encrypt (the web server uses the certificate configured in the interface). The BitTorrent seeder uses its own tracker on the LAN, with DHT, local peer discovery, UPnP and NAT-PMP switched off.
| Destination | Purpose | Trigger | Default | Switch off |
|---|---|---|---|---|
grype.anchore.io |
vulnerability database of the scan, cached in /data/grype-cache |
vulnerability scan started by an admin; database check at most every 2 h | only when a scan runs | do not start scans |
git.thinforge.org |
check for a newer acceptance list (first 4 KB) | after each scan | off | THINFORGE_ACCEPTANCE_LIST_MODE=local (default) |
www.cisa.gov |
KEV catalog: mark actively exploited findings | each scan | off | THINFORGE_KEV_URL= empty (default) |
0.pool.ntp.org, 1.pool.ntp.org |
server time (chrony, time source for the devices) | continuous | on | own time server in the interface (General settings) |
| DNS servers from the setup wizard | forward names outside your network (dnsmasq) | DNS queries of the devices | on | Network → DNS |
| NetBird instance (management, relay, signal, STUN) | VPN for remote devices; reconciliation every minute | continuous once the VPN is set up | off | do not set up / deactivate the VPN |
| your mail server, your webhook address | alert mails and webhooks, test mail, password reset link | event | off | leave empty |
| SourceForge, or any URL you enter | Clonezilla Live ISO; "Download ISO from URL" | click | on click only | upload the ISO instead |
| OCSP service of a public CA | Caddy may fetch the revocation status of an uploaded public-CA certificate | operation | only with such a certificate | — |
https://thinforge.org (from the devices) — agents up to and including v2.24.0 only |
agent diagnosis: does the device have internet at all? Removed from the agent after v2.24.0 (it then checks only DNS name and port of the VPN instance) | only while a VPN enrollment is pending and the VPN instance is unreachable | on (up to v2.24.0) | update the agent; cannot be switched off on older agents |
| NetBird instance (from the devices) | VPN connection of the device | once the VPN is active for the device | off | switch the VPN off for the group or device |
distribution mirrors, pkgs.netbird.io, github.com (grub-btrfs) |
packages, system update and NetBird client while preparing an image in the cloning VM (the VM has unfiltered NAT access) | Tools-ISO installation scripts started by you | on command | restrict at the host firewall |
| vendor download sites (Citrix, Parallels, Horizon) | VDI clients | install-vdi-clients-debian.sh download, run by hand |
on command | — |
git.thinforge.org, Docker Hub, Ubuntu mirrors, download.docker.com |
ThinForge-Release: release repository and ThinForge images (git.thinforge.org), postgres:18-alpine, redis:8-alpine, caddy:latest, guacamole/guacd:1.6.0 and netbirdio/netbird:latest from Docker Hub; Docker installation (install-deps.sh also enables the host's time sync) |
bootstrap-release.sh, install-deps.sh, ./deploy.sh |
on command | mirror the images beforehand |
Docker Hub, git.thinforge.org |
this repository (docker-compose.yml for ./rebuild.sh, docker-compose.registry.yml for ./deploy.sh): the same third-party images as ThinForge-Release — postgres:18-alpine, redis:8-alpine, caddy:latest, guacamole/guacd:1.6.0 and netbirdio/netbird:latest from Docker Hub; ./deploy.sh also pulls the ThinForge images of the chosen channel |
./rebuild.sh, ./deploy.sh |
on command | mirror the images beforehand |
github.com, Docker Hub, dl-cdn.alpinelinux.org, crates.io, npm registry, PyPI, Go module proxy |
building from source (base images alpine, rust, node, golang and, for the frontend image, caddy:2-alpine, all from Docker Hub) |
bootstrap-dev.sh, ./rebuild.sh, agent-go/build-and-sign.sh |
on command | — |
Docker Hub (golang), Go module proxy |
building the agent from the interface — source installations only (THINFORGE_AGENT_BUILD_ENABLED, off in ThinForge-Release) |
once after the first login, then on click | on in source installations | THINFORGE_AGENT_BUILD_ENABLED=false |
Until 2026-10-26 this repository pulled PostgreSQL, Redis and Caddy from reg.mini.dev (Minimus); Minimus ceased operations and switched the registry off on 2026-10-22. Since then they come from Docker Hub as in ThinForge-Release, and reg.mini.dev, auth.mini.dev and us-docker.pkg.dev are no longer needed. The first start with the new PostgreSQL image rebuilds all database indexes once (musl instead of glibc, log lines “Collation der Datenbank …”) before backend and worker go to work.
Installations updated with ./deploy.sh or ./rebuild.sh keep their own settings; only an .env that still carries the former defaults of .env.example (acceptance list check on git.thinforge.org, CISA KEV feed) is switched off once, with a note on the console.
License
Copyright (c) 2024–2026 Andreas Christ — GPL-3.0-or-later.
This program comes with ABSOLUTELY NO WARRANTY; see LICENSE for details.
Contact: info@thinforge.org