← back to LuisForge
LuisForge Docs

Documentation

What LuisForge is, what's actually in the container images, and why the Cmd/server-hosting tab exists.

Overview What's in the prebuilt container Why use the Cmd tab / bore tunnel Actions vs Cmd — what's the difference How the bore tunnel actually works Why not Cloudflared? Why not Windows or macOS? Why not Ubuntu (or Debian, etc.)? Transparency — image provenance Limits & safety

Overview

LuisForge is a small self-hosted git host: repos, issues, commit history, a file browser you can upload to straight from the browser (no git push required), a Docker-build Actions tab, and a Cmd tab that runs arbitrary commands — including long-running servers — inside disposable containers.

What's in the prebuilt container

The one image offered in the Cmd tab's dropdown (luisforge-alpine-full) is built on top of alpine:3.19 with the following already installed, so you don't need to apk add anything yourself before running a command:

ToolWhy it's there
python3 + pipRun scripts, quick http.server demos, install packages on the fly
nodejs + npmRun JS servers/scripts, npm install a project's deps
bashAlpine ships only sh (busybox ash) by default — bash is added for scripts that need it
git, curl, wgetPull extra dependencies or files mid-command if a script needs them
build-base, make, cmakeCompile C/C++ code, native Node/Python extensions that need a real toolchain
vim, lessActually edit or page through a file from inside a running Cmd session
htop, treeSee what's actually running / what a directory looks like without piecing it together from ls
jqParse/filter JSON output from a script or API call without writing a one-off parser
ripgrep (rg)Fast recursive code search — much faster than busybox grep on a real codebase
openssh-clientssh/scp out to somewhere else from inside a run
sqliteInspect/query a .db file directly, e.g. one a script just produced
zip, unzip, tar, gzipReal archive tools beyond busybox's minimal versions
nyancatNo practical reason — it's just there because it's fun, nearly free (a few KB), and it's packaged basically everywhere across Linux distros (Alpine, Debian, Ubuntu, Arch all ship it), so there was no reason not to

Note: python2 was attempted but dropped — Alpine removed it from its repos after version 3.12, and its OpenSSL1.1/libffi7 dependencies directly conflict with python3's OpenSSL3/libffi8 on a modern base. Forcing both to coexist only works by purging python3 entirely, which defeats the point.

Why use the Cmd tab / bore tunnel

A few different reasons this is useful, depending on what you're doing:

Actions vs Cmd — what's the difference

They look similar but solve different problems:

How the bore tunnel actually works

bore is a lightweight TCP tunnel written in Rust. It solves the same basic problem as ngrok or Cloudflare Tunnel: your LuisForge server (and the containers it spins up) sits behind NAT/a firewall with no public IP, so nothing on the internet can connect to it directly — bore gets around that without you touching your router.

  1. When you hit Run with "host it publicly" checked, LuisForge starts your command in a container and asks Docker to publish its port to a random port on 127.0.0.1 on the host.
  2. LuisForge then starts a second container — luisforge-bore — running bore local <that host port> --to bore.pub. It runs with --network host specifically so it can reach 127.0.0.1:<port> on the real host, not just its own container's loopback.
  3. The bore client opens a single outbound TCP connection to bore.pub (a public relay server run by the bore project) and asks for a port to be assigned. Because it's outbound, no firewall/NAT configuration is needed on your end — this is the same trick SSH reverse tunnels and ngrok use.
  4. bore.pub replies with a public port (e.g. bore.pub:41822) and from then on relays any traffic that arrives on that public port back down the existing outbound connection to your bore client, which forwards it to 127.0.0.1:<host port>, which Docker forwards into your container.
  5. LuisForge polls that bore container's logs for the line listening at bore.pub:PORT, parses the port out, and shows it to you as the public address.
  6. Hitting Stop does docker stop on your app container and docker rm -f on the bore container — the outbound connection drops, bore.pub frees the port, and the address stops resolving immediately.

Traffic is not end-to-end encrypted by bore itself — it's a plain TCP relay. Don't send sensitive credentials over a bore-tunneled HTTP endpoint unless the thing you're running adds its own TLS.

Why not Cloudflared?

LuisForge's own backend (and other things on this host, like LuiSearch) actually do use Cloudflare Tunnel elsewhere — so it's not that cloudflared is bad, it's the wrong tool for this specific per-run, ephemeral use case:

In short: cloudflared is the right call for something long-lived and account-backed (like LuiSearch's own backend tunnel); bore is the right call for "give me a URL for the next two minutes and then disappear."

Why not Windows or macOS?

The prebuilt image is Alpine Linux, and that's not really a style choice — the alternatives are either technically impossible or a completely different, much heavier setup on this specific host:

In short: this isn't "Alpine because it's trendy," it's "Alpine because it's the only option that's actually a real, lightweight, instantly-startable container on this host" — Windows and macOS aren't just worse choices here, they're not really on the table.

Why not Ubuntu (or Debian, etc.)?

Unlike Windows/macOS, this one's a genuine trade-off, not an impossibility — Ubuntu/Debian-based images work perfectly fine in Docker on this host. Alpine was picked for a few concrete reasons, with an honest downside too:

The honest downside: Alpine uses musl libc instead of glibc, which is smaller but not 100% ABI-compatible with software built and only tested against glibc — this is exactly what caused the python2 saga documented above (Alpine dropped python2 after 3.12, and pulling in an old build meant for a different libc/OpenSSL/libffi generation turned into an unwinnable dependency conflict). Ubuntu/Debian's glibc base would have sidestepped that specific problem, at the cost of a noticeably larger, slower-to-boot image for every single run. For this feature's "instant, disposable, mostly scripting/serving" use case, that trade favored Alpine — but if you need to run something that's picky about glibc specifically, Alpine is the wrong base and Ubuntu would genuinely be the better call.

Transparency — image provenance

The Docker images used here are not published, audited, or open source artifacts. luisforge-alpine-full and luisforge-bore are built locally by this specific LuisForge instance from a Dockerfile that lives alongside the server code — they are not pulled from Docker Hub, not signed, and not independently verifiable by you as a user beyond trusting whoever runs this instance.

Limits & safety