Release Server
How to set up and deploy the lightshell-server for hosting app updates.
The lightshell-server is a lightweight Hono-based TypeScript server purpose-built for hosting signed LightShell releases. It handles update manifests, binary storage, Ed25519 signature verification, and provides a dashboard for monitoring downloads.
You do not need this server to ship updates — you can host update manifests on any static file server or GitHub Releases. The release server adds convenience features like automatic manifest generation, a web dashboard, and download analytics.
One-Click Deploy
Section titled “One-Click Deploy”Deploy the release server to your preferred platform in one click. Each button will fork the repo, prompt you for environment variables, and deploy automatically.
| Platform | Deploy | Free Tier | Notes |
|---|---|---|---|
| Railway | $5/mo credit | Persistent disk, automatic HTTPS | |
| Render | Free tier available | Auto-deploy from GitHub, managed TLS | |
| Cloudflare Workers | — | 100K req/day free | Fastest option, see manual setup below |
| Fly.io | — | 3 shared VMs free | See manual setup below |
After deploying, you will need to set two environment variables:
LIGHTSHELL_API_KEY— generate withopenssl rand -hex 32PUBLIC_KEY— your Ed25519 public key (see Signing Keys)
What the one-click deploy does
Section titled “What the one-click deploy does”- Forks
lightshell-dev/lightshell-serverinto your account - Prompts you for required environment variables
- Builds and deploys the server
- Gives you a public HTTPS URL to use as your updater endpoint
Manual Deploy
Section titled “Manual Deploy”If you prefer CLI deployments or need more control over configuration, use one of the methods below.
Cloudflare Workers (Recommended)
Section titled “Cloudflare Workers (Recommended)”# Clone the release servergit clone https://github.com/lightshell-dev/lightshell-servercd lightshell-server
# Install dependenciesnpm install
# Configurecp wrangler.example.toml wrangler.toml# Edit wrangler.toml with your account details
# Set secretsnpx wrangler secret put LIGHTSHELL_API_KEYnpx wrangler secret put PUBLIC_KEY
# Deploynpx wrangler deployYour server will be live at https://lightshell-server.<your-subdomain>.workers.dev.
Railway
Section titled “Railway”git clone https://github.com/lightshell-dev/lightshell-servercd lightshell-server
# Install Railway CLI: https://docs.railway.com/guides/clirailway loginrailway initrailway up
# Set environment variables in the Railway dashboardOr use the Railway dashboard directly:
- Go to railway.com/new
- Select Deploy from GitHub repo
- Connect
lightshell-dev/lightshell-server(or your fork) - Add environment variables:
LIGHTSHELL_API_KEY,PUBLIC_KEY,STORAGE_BACKEND=local,STORAGE_PATH=/data/releases - Add a volume mounted at
/datafor persistent storage - Deploy
Render
Section titled “Render”Or manually:
- Fork
lightshell-dev/lightshell-serveron GitHub - Create a new Web Service on render.com
- Connect your forked repository
- Set Build Command to
npm install && npm run build - Set Start Command to
npm start - Add environment variables in the Render dashboard
- Add a Disk mounted at
/datafor local storage (if not using S3) - Deploy
Fly.io
Section titled “Fly.io”git clone https://github.com/lightshell-dev/lightshell-servercd lightshell-server
fly launchfly secrets set LIGHTSHELL_API_KEY=your-secret-keyfly secrets set PUBLIC_KEY=your-ed25519-public-keyfly deploySelf-Hosted
Section titled “Self-Hosted”Run the server on any machine with Node.js 20+ or Bun:
git clone https://github.com/lightshell-dev/lightshell-servercd lightshell-servernpm installnpm run build
# Set environment variablesexport LIGHTSHELL_API_KEY="your-secret-key"export PUBLIC_KEY="your-ed25519-public-key"export STORAGE_BACKEND="local"export STORAGE_PATH="/var/lib/lightshell-releases"export PORT=3000
npm startPut it behind a reverse proxy (Caddy, nginx) with HTTPS. The updater requires HTTPS in production builds.
Environment Variables
Section titled “Environment Variables”| Variable | Required | Description |
|---|---|---|
LIGHTSHELL_API_KEY | Yes | API key for authenticating upload requests from CI/CD. Generate with openssl rand -hex 32. |
PUBLIC_KEY | Yes | Your Ed25519 public key for verifying release signatures. See Signing Keys. |
STORAGE_BACKEND | No | Where to store release binaries. Options: r2 (Cloudflare R2, default for Workers), s3, local. |
STORAGE_PATH | No | Path for local storage backend. Default: ./releases. |
S3_BUCKET | No | S3 bucket name (when using s3 backend). |
S3_REGION | No | S3 region (when using s3 backend). |
R2_BUCKET | No | R2 bucket name (when using r2 backend). Default: lightshell-releases. |
PORT | No | Server port for self-hosted deployments. Default: 3000. |
Connecting Your App
Section titled “Connecting Your App”Once the server is running, point your app’s updater config to it.
lightshell.json:
{ "name": "my-app", "version": "1.0.0", "entry": "src/index.html", "updater": { "enabled": true, "endpoint": "https://your-release-server.example.com/api/latest/my-app", "interval": "24h" }}The server generates the update manifest automatically from uploaded releases. The endpoint URL follows the pattern:
https://<server>/api/latest/<app-name>Uploading Releases
Section titled “Uploading Releases”Upload signed release binaries using the CLI or a direct HTTP request.
With the CLI
Section titled “With the CLI”# Build your applightshell build
# Upload (reads LIGHTSHELL_RELEASE_SERVER and LIGHTSHELL_RELEASE_TOKEN from env)lightshell release --server https://your-release-server.example.comWith curl
Section titled “With curl”curl -X POST https://your-release-server.example.com/api/releases \ -H "Authorization: Bearer your-api-key" \ -F "app=my-app" \ -F "version=1.2.0" \ -F "platform=darwin-arm64" \ -F "notes=Bug fixes and performance improvements" \ -F "signature=base64-encoded-ed25519-signature" \ -F "file=@dist/my-app-darwin-arm64.tar.gz"The server computes the SHA256 hash automatically and stores it in the manifest.
Dashboard
Section titled “Dashboard”The release server includes a web dashboard at the root URL (https://your-server.example.com/). The dashboard shows:
- Current version for each platform
- Download counts per version and platform
- Release history with timestamps and release notes
- Health status of the storage backend
The dashboard is read-only and does not require authentication. It does not expose API keys, private keys, or download URLs — only version numbers, release notes, and aggregate statistics.
API Endpoints
Section titled “API Endpoints”| Method | Path | Description |
|---|---|---|
GET | /api/latest/:app | Returns the update manifest for the latest version. This is what the updater fetches. |
POST | /api/releases | Upload a new release binary. Requires Authorization header. |
GET | /api/releases/:app | List all releases for an app (version history). |
DELETE | /api/releases/:app/:version | Delete a specific release. Requires Authorization header. |
GET | /health | Health check endpoint. Returns 200 OK. |
Storage Backends
Section titled “Storage Backends”Cloudflare R2
Section titled “Cloudflare R2”The default for Cloudflare Workers deployments. R2 provides S3-compatible storage with no egress fees. Binaries are stored in an R2 bucket bound to the Worker.
Amazon S3
Section titled “Amazon S3”For self-hosted or Railway/Render deployments. Set STORAGE_BACKEND=s3 and provide S3_BUCKET and S3_REGION. The server uses the AWS SDK, so standard credential resolution applies (environment variables, IAM role, etc.).
Local Filesystem
Section titled “Local Filesystem”For development or simple self-hosted setups. Set STORAGE_BACKEND=local and STORAGE_PATH to a directory with sufficient disk space. Make sure the directory is backed up — losing it means losing all release binaries.
Next Steps
Section titled “Next Steps”- Signing Keys — generate Ed25519 keys for signing releases
- CI/CD — automate the build-sign-upload pipeline with GitHub Actions
- Update Security — understand the security model