diff --git a/.github/glyphs/bolt.svg b/.github/glyphs/bolt.svg new file mode 100644 index 0000000..bf8e109 --- /dev/null +++ b/.github/glyphs/bolt.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/broadcast.svg b/.github/glyphs/broadcast.svg new file mode 100644 index 0000000..293d112 --- /dev/null +++ b/.github/glyphs/broadcast.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/database.svg b/.github/glyphs/database.svg new file mode 100644 index 0000000..1aa500b --- /dev/null +++ b/.github/glyphs/database.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/document.svg b/.github/glyphs/document.svg new file mode 100644 index 0000000..5468e9c --- /dev/null +++ b/.github/glyphs/document.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/elephant.svg b/.github/glyphs/elephant.svg new file mode 100644 index 0000000..9080985 --- /dev/null +++ b/.github/glyphs/elephant.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/leaf.svg b/.github/glyphs/leaf.svg new file mode 100644 index 0000000..5951662 --- /dev/null +++ b/.github/glyphs/leaf.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/mail.svg b/.github/glyphs/mail.svg new file mode 100644 index 0000000..d90a43e --- /dev/null +++ b/.github/glyphs/mail.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/queue.svg b/.github/glyphs/queue.svg new file mode 100644 index 0000000..818b832 --- /dev/null +++ b/.github/glyphs/queue.svg @@ -0,0 +1 @@ + diff --git a/.github/glyphs/search.svg b/.github/glyphs/search.svg new file mode 100644 index 0000000..e3af19f --- /dev/null +++ b/.github/glyphs/search.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/adminer.svg b/.github/logos/adminer.svg new file mode 100644 index 0000000..c2ce025 --- /dev/null +++ b/.github/logos/adminer.svg @@ -0,0 +1,3 @@ + + + diff --git a/.github/logos/beanstalkd.svg b/.github/logos/beanstalkd.svg new file mode 100644 index 0000000..3a38252 --- /dev/null +++ b/.github/logos/beanstalkd.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/clickhouse.svg b/.github/logos/clickhouse.svg new file mode 100644 index 0000000..4545fe2 --- /dev/null +++ b/.github/logos/clickhouse.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/elasticsearch.svg b/.github/logos/elasticsearch.svg new file mode 100644 index 0000000..01be8f8 --- /dev/null +++ b/.github/logos/elasticsearch.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/elasticvue.svg b/.github/logos/elasticvue.svg new file mode 100644 index 0000000..eea2015 --- /dev/null +++ b/.github/logos/elasticvue.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/gotenberg.svg b/.github/logos/gotenberg.svg new file mode 100644 index 0000000..bf4303f --- /dev/null +++ b/.github/logos/gotenberg.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/kafka-ui.svg b/.github/logos/kafka-ui.svg new file mode 100644 index 0000000..2d1e147 --- /dev/null +++ b/.github/logos/kafka-ui.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/kafka.svg b/.github/logos/kafka.svg new file mode 100644 index 0000000..058f352 --- /dev/null +++ b/.github/logos/kafka.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/localstack.svg b/.github/logos/localstack.svg new file mode 100644 index 0000000..33aebf6 --- /dev/null +++ b/.github/logos/localstack.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/.github/logos/mariadb.svg b/.github/logos/mariadb.svg new file mode 100644 index 0000000..33c124c --- /dev/null +++ b/.github/logos/mariadb.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/memcached.svg b/.github/logos/memcached.svg new file mode 100644 index 0000000..ba9180f --- /dev/null +++ b/.github/logos/memcached.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/mercure.svg b/.github/logos/mercure.svg new file mode 100644 index 0000000..16770d6 --- /dev/null +++ b/.github/logos/mercure.svg @@ -0,0 +1,4 @@ + + + + diff --git a/.github/logos/mongo-express.svg b/.github/logos/mongo-express.svg new file mode 100644 index 0000000..c4f0721 --- /dev/null +++ b/.github/logos/mongo-express.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/mongo.svg b/.github/logos/mongo.svg new file mode 100644 index 0000000..cc12450 --- /dev/null +++ b/.github/logos/mongo.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/opensearch-dashboards.svg b/.github/logos/opensearch-dashboards.svg new file mode 100644 index 0000000..eea2015 --- /dev/null +++ b/.github/logos/opensearch-dashboards.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/opensearch.svg b/.github/logos/opensearch.svg new file mode 100644 index 0000000..17e55cc --- /dev/null +++ b/.github/logos/opensearch.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/pgadmin.svg b/.github/logos/pgadmin.svg new file mode 100644 index 0000000..a1fd5d3 --- /dev/null +++ b/.github/logos/pgadmin.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/phpmyadmin.svg b/.github/logos/phpmyadmin.svg new file mode 100644 index 0000000..e1693c7 --- /dev/null +++ b/.github/logos/phpmyadmin.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/postgres-pgvector.svg b/.github/logos/postgres-pgvector.svg new file mode 100644 index 0000000..9e24063 --- /dev/null +++ b/.github/logos/postgres-pgvector.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/postgres-timescaledb.svg b/.github/logos/postgres-timescaledb.svg new file mode 100644 index 0000000..9e24063 --- /dev/null +++ b/.github/logos/postgres-timescaledb.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/rabbitmq.svg b/.github/logos/rabbitmq.svg new file mode 100644 index 0000000..ed548d3 --- /dev/null +++ b/.github/logos/rabbitmq.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/redisinsight.svg b/.github/logos/redisinsight.svg new file mode 100644 index 0000000..6afed08 --- /dev/null +++ b/.github/logos/redisinsight.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/selenium.svg b/.github/logos/selenium.svg new file mode 100644 index 0000000..f6162dd --- /dev/null +++ b/.github/logos/selenium.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/soketi.svg b/.github/logos/soketi.svg new file mode 100644 index 0000000..826e53c --- /dev/null +++ b/.github/logos/soketi.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/solr.svg b/.github/logos/solr.svg new file mode 100644 index 0000000..6e77eb7 --- /dev/null +++ b/.github/logos/solr.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.github/logos/spamassassin.svg b/.github/logos/spamassassin.svg new file mode 100644 index 0000000..11ea145 --- /dev/null +++ b/.github/logos/spamassassin.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/stripe-mock.svg b/.github/logos/stripe-mock.svg new file mode 100644 index 0000000..c602790 --- /dev/null +++ b/.github/logos/stripe-mock.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/typesense-dashboard.svg b/.github/logos/typesense-dashboard.svg new file mode 100644 index 0000000..eea2015 --- /dev/null +++ b/.github/logos/typesense-dashboard.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/typesense.svg b/.github/logos/typesense.svg new file mode 100644 index 0000000..eaec98b --- /dev/null +++ b/.github/logos/typesense.svg @@ -0,0 +1 @@ + diff --git a/.github/logos/valkey.svg b/.github/logos/valkey.svg new file mode 100644 index 0000000..d31eeb0 --- /dev/null +++ b/.github/logos/valkey.svg @@ -0,0 +1 @@ + diff --git a/.github/scripts/readme_logos.py b/.github/scripts/readme_logos.py new file mode 100644 index 0000000..b486825 --- /dev/null +++ b/.github/scripts/readme_logos.py @@ -0,0 +1,82 @@ +"""Render the README's service logos from the store's own marks. + +The marks under services/ are monochrome by contract, which GitHub would draw +black and lose on a dark theme. This paints each one in its declared colour on +a white tile, so the README reads the same in either theme. A service with no +mark gets the lerd glyph its `icon` names, in its category's tint, which is how +the dashboard draws it too. + +Run from the repo root after adding or changing a service: + python3 .github/scripts/readme_logos.py +""" + +import json +import pathlib +import re +import sys + +ROOT = pathlib.Path(__file__).resolve().parents[2] +GLYPHS = ROOT / ".github" / "glyphs" +OUT = ROOT / ".github" / "logos" + +# The -600 tones of lerd's per-category tints (presetCategories.ts). +CATEGORY_TINT = { + "databases": "#4f46e5", + "cache": "#d97706", + "messaging": "#7c3aed", + "search": "#0284c7", + "mail": "#e11d48", + "admin": "#059669", + "storage": "#0891b2", + "testing": "#c026d3", + "other": "#6b7280", +} + +TILE = """\ +\ +{body} +""" + + +def split(svg: str, source: str) -> tuple[str, str]: + root = re.match(r'\s*]*viewBox="([^"]+)"[^>]*>(.*)\s*$', svg, re.S) + if not root: + sys.exit(f"{source} has no root") + return root.group(1), root.group(2) + + +def services() -> list[dict]: + # Newer schemas list presets older binaries cannot read, so the README + # takes every index there is and lets a later one win a name. + merged = {} + for index in [ROOT / "services" / "index.json", *sorted(ROOT.glob("schema/*/services/index.json"))]: + for entry in json.loads(index.read_text())["services"]: + merged[entry["name"]] = entry + return list(merged.values()) + + +def render(entry: dict) -> str: + name = entry["name"] + mark = ROOT / "services" / f"{name}.svg" + if mark.exists(): + viewbox, body = split(mark.read_text(), mark.name) + return TILE.format(inset=13, size=38, viewbox=viewbox, attrs=f' fill="{entry["color"]}"', body=body) + + glyph = GLYPHS / f"{entry['icon']}.svg" + if not glyph.exists(): + sys.exit(f"{name} has no mark and its icon {entry['icon']!r} has no .github/glyphs/{entry['icon']}.svg") + color = entry.get("color") or CATEGORY_TINT[entry["category"]] + viewbox, body = split(glyph.read_text(), glyph.name) + attrs = f' fill="none" stroke="{color}"' + return TILE.format(inset=12, size=40, viewbox=viewbox, attrs=attrs, body=body.replace("currentColor", color)) + + +def main() -> None: + OUT.mkdir(exist_ok=True) + for entry in services(): + (OUT / f"{entry['name']}.svg").write_text(render(entry)) + print(f"wrote .github/logos/{entry['name']}.svg") + + +if __name__ == "__main__": + main() diff --git a/README.md b/README.md index c814e84..6fa2524 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,35 @@ -# Lerd Service Store - -> The community-driven store of service presets that powers -> [Lerd](https://lerd.sh) — add a database, cache, search engine, -> or admin dashboard by editing YAML, no binary release required. - -[![Part of Lerd](https://img.shields.io/badge/part%20of-lerd-ff2d20)](https://lerd.sh) -[![Docs](https://img.shields.io/badge/docs-lerd.sh-blue)](https://lerd.sh/usage/service-presets) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) +

Lerd Service Store

+ +

+ The community-driven store of service presets that powers Lerd.
+ Add a database, cache, search engine, or admin dashboard by editing YAML, no binary release required. +

+ +

+ Part of Lerd + Docs + License: MIT +

+ +

+ adminer + clickhouse + elasticsearch + kafka + localstack + mariadb + mercure + mongo + opensearch + phpmyadmin + postgres-pgvector + postgres-timescaledb + rabbitmq + selenium + solr + stripe-mock + valkey +

Run `lerd service search`, pick something, `lerd service preset ` — and Lerd pulls the matching preset from this store, then knows exactly how to run it: which image and ports, how to wire your project's `.env`, which admin dashboard to embed, what it depends on, and which config files to mount for auto-login. Everything is a single YAML file. Add a service here and every Lerd install can use it within 24 hours, with no new Lerd release and no Go code. @@ -30,56 +53,58 @@ All of it is data. None of it ships in the binary. **Databases** -| Service | What it is | -|---------|------------| -| `clickhouse` | ClickHouse column-oriented analytics database, with its own SQL console | -| `mariadb` | MariaDB, the MySQL-compatible server (multi-version) | -| `mongo` | MongoDB document database | -| `postgres-pgvector` | PostgreSQL + pgvector for vector search (multi-version) | -| `postgres-timescaledb` | PostgreSQL + TimescaleDB for time-series (multi-version) | +| | Service | What it is | +|:-:|---|---| +| | `clickhouse` | ClickHouse column-oriented analytics database, with its own SQL console | +| | `mariadb` | MariaDB, the MySQL-compatible server (multi-version) | +| | `mongo` | MongoDB document database | +| | `postgres-pgvector` | PostgreSQL + pgvector for vector search (multi-version) | +| | `postgres-timescaledb` | PostgreSQL + TimescaleDB for time-series (multi-version) | **Admin dashboards** — open inside the Lerd UI, auto-logged-in -| Service | For | -|---------|-----| -| `phpmyadmin` | every installed MySQL / MariaDB service | -| `pgadmin` | every installed PostgreSQL service | -| `mongo-express` | MongoDB | -| `redisinsight` | Redis | -| `elasticvue` | Elasticsearch | -| `typesense-dashboard` | Typesense | -| `opensearch-dashboards` | OpenSearch | -| `adminer` | every installed MySQL / MariaDB / PostgreSQL / ClickHouse service | +| | Service | For | +|:-:|---|---| +| | `adminer` | every installed MySQL / MariaDB / PostgreSQL / ClickHouse service | +| | `elasticvue` | Elasticsearch | +| | `kafka-ui` | Kafka | +| | `mongo-express` | MongoDB | +| | `opensearch-dashboards` | OpenSearch | +| | `pgadmin` | every installed PostgreSQL service | +| | `phpmyadmin` | every installed MySQL / MariaDB service | +| | `redisinsight` | Redis | +| | `typesense-dashboard` | Typesense | **Search & analytics** -| Service | What it is | -|---------|------------| -| `elasticsearch` | Elasticsearch single-node engine | -| `opensearch` | OpenSearch single-node engine | -| `typesense` | Typesense typo-tolerant search | -| `solr` | Apache Solr, the search backend Drupal and TYPO3 expect | +| | Service | What it is | +|:-:|---|---| +| | `elasticsearch` | Elasticsearch single-node engine | +| | `opensearch` | OpenSearch single-node engine | +| | `solr` | Apache Solr, the search backend Drupal and TYPO3 expect | +| | `typesense` | Typesense typo-tolerant search | **Cache, queues & messaging** -| Service | What it is | -|---------|------------| -| `valkey` | Valkey, the Redis-compatible cache (coexists with Redis) | -| `memcached` | Memcached in-memory cache | -| `rabbitmq` | RabbitMQ broker with management UI | -| `soketi` | Pusher-compatible WebSocket server | -| `beanstalkd` | Beanstalkd work queue | -| `mercure` | Mercure hub for server-sent events, the Symfony realtime transport | +| | Service | What it is | +|:-:|---|---| +| | `beanstalkd` | Beanstalkd work queue | +| | `kafka` | Apache Kafka event streaming broker | +| | `memcached` | Memcached in-memory cache | +| | `mercure` | Mercure hub for server-sent events, the Symfony realtime transport | +| | `rabbitmq` | RabbitMQ broker with management UI | +| | `soketi` | Pusher-compatible WebSocket server | +| | `valkey` | Valkey, the Redis-compatible cache (coexists with Redis) | **Testing & tooling** -| Service | What it is | -|---------|------------| -| `selenium` | Headless Chromium with a noVNC viewer for browser tests | -| `stripe-mock` | Stripe API mock server | -| `gotenberg` | Gotenberg API for PDF and document conversion | -| `localstack` | LocalStack, the AWS APIs run locally (SQS, SES, DynamoDB, Secrets Manager) | -| `spamassassin` | SpamAssassin scoring backend for the Mailpit catcher | +| | Service | What it is | +|:-:|---|---| +| | `gotenberg` | Gotenberg API for PDF and document conversion | +| | `localstack` | LocalStack, the AWS APIs run locally (SQS, SES, DynamoDB, Secrets Manager) | +| | `selenium` | Headless Chromium with a noVNC viewer for browser tests | +| | `spamassassin` | SpamAssassin scoring backend for the Mailpit catcher | +| | `stripe-mock` | Stripe API mock server | Don't see what you need? [Add it](#contributing) — that's what this repo is for. @@ -102,7 +127,7 @@ New services and version bumps are welcome — this store is only as good as the 1. Fork this repo 2. Add or update `services/.yaml` -3. Optionally add the service's own mark as `services/.svg` (see below) +3. Optionally add the service's own mark as `services/.svg` (see below), then run `python3 .github/scripts/readme_logos.py` to draw its tile for this README 4. Add or update the matching entry in `services/index.json` (name, description, and optionally family, dashboard, depends_on) 5. Open a pull request @@ -208,6 +233,8 @@ A family is the other way round. Every member of one is that engine, so they all carry its mark and its colour: pgvector and TimescaleDB are Postgres, and both draw the Postgres elephant in Postgres blue rather than a mark of their own. +The coloured tiles in this README are not the marks themselves. `.github/scripts/readme_logos.py` paints each mark in its declared colour on a white tile, so GitHub shows it in either theme, and a service without one gets the lerd glyph its `icon` names in its category's tint, from copies kept in `.github/glyphs/`. It writes the result to `.github/logos/`; run it again whenever a service, its mark or its colour changes. + See the [service presets documentation](https://lerd.sh/usage/service-presets) for the full schema reference and every available field. ## License