Miget
Run Loomplane on Miget as a Compose Stack built from this repository, with a managed PostgreSQL database.
You can run Loomplane on Miget as a Compose Stack built from deployments/miget. Miget builds the image from the repository, so you don't need a published release. You get the API and dashboard, the analysis worker and a managed PostgreSQL database.
Deploy
Generate a secret key first and keep it in your secret manager:
openssl rand -base64 32Then create the stack in Miget:
- Choose Compose Stack, pick the repository and the branch you want to track, and set the compose path to
deployments/miget. - On the review step Miget asks for
LOOMPLANE_SECRET_KEYand fills in a random value. Replace it with your key. Loomplane only accepts 32 bytes encoded as base64 and won't start with anything else. - Pick a Resource with room for the stack. It asks for 1.5 GB of RAM (512 MB each for the API, the worker and the database), a 2 GB artifact volume and 2 GB of database storage. If analysis of a big repository runs out of memory, raise the worker's
ramincompose.miget.yamlfirst. - Deploy, wait for both builds, and open the
loomplaneapp's URL.
Create your account and organization, then connect a repository.
Loomplane's encryption keys come from that secret, and stored credentials can't be decrypted without it, so set it once and leave it alone on later deploys.
What Miget runs
| Service | On Miget | Notes |
|---|---|---|
loomplane | Public app on port 5000 | API and dashboard, with the artifact volume |
loomplane-worker | Private app | Repository analysis |
db | Managed PostgreSQL | Backed up daily by Miget |
compose.miget.yaml switches both apps to production and wires them up. The public URL comes from Miget's ${{loomplane.public_url}} and the database URL from ${{db.url}}, so you never type either one. If you move to a custom domain, check that both apps see it in LOOMPLANE_PUBLIC_URL, because sign-in redirects are built from that address.
Miget runs every Compose service as its own app and drops entrypoint: and command:, which is why the image picks its process from LOOMPLANE_PROCESS. It's api unless you set worker. Any other value stops the container with an error, so a typo can't quietly start a second API.
Optional settings
The stack leaves out the GitHub App, email and recovery storage. Add them as environment variables on the Miget apps once the stack is up:
- The six
LOOMPLANE_GITHUB_*credentials go on both apps. Set them together. See Private repositories. - The
LOOMPLANE_NOTIFICATIONS_*SMTP settings go onloomplane. Production uses implicit TLS, usually on port 465. LOOMPLANE_BACKUP_URLandLOOMPLANE_BACKUP_BUCKETgo onloomplaneif you want recovery objects off the artifact volume.
Production on Docker explains each one.
Try it locally
Plain docker compose ignores compose.miget.yaml, so you can run the same stack on your laptop in development mode, with a Postgres container standing in for the managed database:
cd deployments/miget
cp .env.example .env
# put the output of `openssl rand -base64 32` in LOOMPLANE_SECRET_KEY
docker compose up --build --waitOpen http://localhost:5000.
Things to know
Miget builds the image twice, once per app, and each build compiles the dashboard and the Go binaries. Expect the first deploy to take a while.
On the first deploy the worker can start before the API has finished migrating the database. It restarts until the migrations are in, then settles.
Miget picks the PostgreSQL version for the managed database, while the production Docker stack pins PostgreSQL 17. Check which major version you got before you restore a backup from elsewhere.
Miget backs up the database every day and keeps those backups for at least seven days. It doesn't back up the artifact volume. Point LOOMPLANE_BACKUP_URL at independent object storage if you need recovery objects to survive losing that volume.