Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Metroline Logo



Open Source Continuous Integration and Delivery platform built with Docker, NodeJS, React, D3 and

Found a security issue ? Please let us know !



  • supports multi-runner (multi-machine not supported yet)
  • use docker images for jobs
  • define docker images at the job level or globally
  • branch conditions
  • status conditions
  • shared workspace, no artifact headache
  • secret masking in logs (best effort)
  • compatible with Gitlab (support subgroups), Gitea (coming soon: Github, Bitbucket, Gogs)
  • easy install with Docker and Docker Compose
  • model complex workflows (we haven't yet implemented workspace merging)
  • define secrets at the repo level or globally
  • restrict secrets to protected branches
  • restrict secrets to specific branches

Why we wrote Metroline

We wrote Metroline because:

  • Gitlab CI secret masking doesn't support short or multiline secrets (but we acknowledge that it's not an easy task) even though a "best effort" strategy could be taken [source]
  • Gitlab CI cache can be unexpected, to the point where we've sometimes had to artifact node_modules, even though we used per-branch, per-repo cache keys ($CI_PROJECT_ID-$CI_BUILD_REF_NAME)
  • Gitlab CI is slow with pipelines that use cache/artifacts because it has to copy them between jobs
  • Drone CI doesn't support Gitlab subgroups [source]
  • CircleCI is not self hosted
  • Github Actions is not open source and cannot be self-hosted
  • TravisCI installation seems difficult with docker-compose, and we're not huge fans of the syntax, but it's open source 👍
  • Getting a feature request implemented is merely impossible or takes months in existing solutions 😞
  • ... it's A LOT of fun, and really cool :)

If you're using Metroline and would like to add something to this list, feel free to make a PR !


We're looking for help in the first place to write tests. We know it's boring, but this would help us stabilize the current version of Metroline.

Our roadmap is available here.


Using Gitea

  1. Run docker-compose -f ./docker-compose-dev.yml up -d.
  2. Configure Gitea
  3. Run docker-compose -f ./docker-compose-dev.yml down.
  4. Edit ./data/gitea/gitea/conf/app.ini:
    DOMAIN           = <your-ip>
    SSH_DOMAIN       = <your-ip>
    ROOT_URL         = http://<your-ip>:3003/
    SSH_PORT         = 222
  5. Run docker-compose -f ./docker-compose-dev.yml up -d.

This way, URLs in webhook commits will allow proper clones from inside a Docker container (see limitations).

Using Github

  1. Start a tunnel to your local Metroline server with ngrok http 3001.
  2. Create an OAuth app and change the Client ID and Client Secret. Make sure to set the callback URL to the HTTPS url provided by Ngrok.
  3. In your .server.env, set cookie settings so that Chrome allows cross-site requests with your Metroline auth cookie:


Use mkcert to generate a certificate and key:

brew install mkcert nss
mkcert -install
mkcert localhost

then update your .env with:


For runners to register properly, you need to set NODE_EXTRA_CA_CERTS to the path of mkcert's root CA (which should be in the directory printed in your console when running mkcert -install - you can always re-run this command). Make sure NODE_EXTRA_CA_CERTS is set prior to running npm start, otherwise it won't work.


Metroline is an Open Source Continuous Integration and Delivery (CICD) platform built with Docker, Node, React, MongoDB,, D3 and Typescript.



Security policy





No packages published