Self-hosted service
Clivern/Peanut avatar
Clivern/Peanut

Clivern/Peanut: container-backed databases and services for test pipelines

🐺 Deploy Databases and Services Easily for Development and Testing Pipelines.

724 stars29 forksGoMIT

At a glance

What is it?
Peanut is a Go service that provisions databases, brokers and observability tools through Docker on demand, exposing them over a REST API, an admin dashboard and a CLI. It is aimed at development and testing pipelines where mocking a real dependency is not an option.
Who is it for?
Adopt Peanut if your team already runs Docker on a shared Linux host and wants ephemeral MySQL, Redis or RabbitMQ instances created from a pipeline step rather than from a checked-in compose file. Skip it if you need Kubernetes-native provisioning, a managed cloud database, or anything with a formal support contract, since the newest release listed is v0.7.0 from 2023-02-23 and the README documents no rollback path for a failed deploy.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Peanut actually provisions, and for whom

Integration tests that touch a real database usually fall into one of three patterns: a long-lived shared instance that accumulates state, a docker-compose file checked into the repository, or a mock that never exercises the driver. Peanut takes a fourth route. It runs as a service on a host, and when you ask it for a Redis or MySQL instance it starts a container, waits for it, and hands back the address and port to connect to. The README frames the target audience narrowly: development, manual testing and automated testing pipelines "where mocking is not possible and test drives."

The supported list is broad rather than deep. It covers MySQL, MariaDB, PostgreSQL, Redis, Etcd, Grafana, Elasticsearch, MongoDB, Graphite, Prometheus, Zipkin, Memcached, Mailhog, Jaeger, RabbitMQ, Consul, Vault, Cassandra, Minio, Docker Registry, Ghost, Httpbin, Nagios and Etherpad. That spread matters more than any single entry: a test suite that needs Postgres, RabbitMQ and a fake SMTP endpoint can get all three from one API instead of three compose files. Mailhog and Httpbin in particular are the kind of throwaway dependency that is annoying to stand up by hand and easy to forget to tear down.

The README is candid about the alternative: the same result is achievable with "a bunch of yaml files or using a configuration management tool or a package manager like helm," and it positions Peanut as smaller and faster to work with. That is an honest framing, and it also tells you where the project does not compete. It is not a configuration management system and it does not try to keep a declared state reconciled.

The API, the dashboard and the CLI over a Docker driver

The architecture visible in the repository is a Go binary with three front ends and one execution layer. The go.mod file lists gin for HTTP routing, cobra for the command line, viper for configuration, logrus for logging, prometheus/client_golang for metrics, and go.etcd.io/etcd/client/v3, which confirms etcd is a real dependency rather than an optional add-on. The top-level layout separates cmd/, core/, pkg/, sdk/, web/ and deployment/, so the API and the CLI sit on top of shared core logic rather than duplicating it.

Underneath, the containerization driver is Docker. The distributed config exposes it as a single key, containerization.driver, defaulting to docker, with the comment "supported docker" beside it. Two related settings sit in the same block: autoClean, which the comment describes as cleaning up stale images, volumes and networks, and cacheTagsTimeInMinutes, defaulting to 10080 minutes, which caches Docker image tags for a week. The storage layer is local only, with type defaulting to local and a path defaulting to /tmp.

The data flow for a deploy is visible in the README's own curl example. A POST to /api/v1/service with a service name and a deleteAfter value returns a task object with status PENDING and type service.deploy. The instance is not ready at that point; the response carries a task id, not connection details. A subsequent GET on the same endpoint returns the services array, and only there do you see the configs block with address, password and port. Treating deploy as asynchronous is the single most important thing to get right in a pipeline, because a script that reads the POST response for a port will find nothing to read.

Installing Peanut on Ubuntu and provisioning the first Redis instance

The README's Ubuntu path is a single bootstrap script. It installs etcd, docker, docker-compose and peanut, and the README warns that a cold start "may take a while." Peanut then listens on port 80, with the dashboard at http://<public-ip>.

bash
bash < <(curl -s https://raw.githubusercontent.com/Clivern/Peanut/main/deployment/linux/install.sh)

# Get The Public IP
curl https://ipinfo.io/ip

After the script finishes, open /etc/peanut/config.prod.yml and set the app.hostname value to your public IP or hostname, then restart the service. The README shows the key with its environment variable fallback, PEANUT_API_HOSTNAME, defaulting to 127.0.0.1.

bash
systemctl restart peanut

Now provision a Redis instance that deletes itself after ten minutes. Note the x-api-key header: the API is key-protected, and the key is configured under the api block in the config file.

bash
curl -X POST http://$PUBLIC_IP/api/v1/service \
  -d '{"service":"redis","configs": {},"deleteAfter":"10min"}' \
  -H 'x-api-key: ~api~key~here~'

The response is a task, not a service. It contains createdAt, an id, a service field, status PENDING and type service.deploy. Poll the collection endpoint to find the connection details:

bash
curl -X GET http://$PUBLIC_IP/api/v1/service -H 'x-api-key: ~api~key~here~'

Each entry in the services array carries id, service, configs, deleteAfter, createdAt and updatedAt. The configs block is what your test harness needs: address, password and port. In the README's sample output two Redis instances appear with ports 49155 and 49156, one with deleteAfter set to 10min and one with an empty string. The README also documents an upgrade script at deployment/linux/upgrade.sh, invoked the same way as the installer. For a manual install, the README points at the release tarballs, extracted with a curl and tar pipeline that reads the latest tag from the GitHub API, and requires etcd plus docker and docker-compose to be installed separately.

Where Peanut stops being the right tool

The most concrete limitation is that deletion is scheduled, not transactional. The deleteAfter field is a string such as "10min", and the README shows an empty string for instances that are meant to persist. Nothing in the documented API describes what happens if the Peanut process restarts while a deleteAfter timer is pending, and the README does not document rollback for a failed deploy. A task that returns PENDING and then never resolves leaves your pipeline waiting on a port that will not open. Budget for a timeout and a cleanup step of your own.

Storage is local only. The config schema states this directly: type defaults to local and the only documented value is local. That means service metadata lives on the host running Peanut. There is no documented replication or backup path, so a rebuilt host starts from an empty service list while orphaned containers may still be running on the Docker daemon. This is a single-host design, and it should be treated as one.

The driver is Docker, and the config comment says as much: "supported docker." If your organisation has standardised on Kubernetes, Peanut does not meet you there. It also does not manage cloud-managed databases, so a team whose integration tests must run against the same engine version and parameter group as production will find Peanut's containers a different environment, not a smaller copy of production. And the versioning is worth reading carefully: the newest release listed is v0.7.0 from 2023-02-23, following v0.6.0 the same day and v0.5.0 from 2022-06-26. The last push to the repository was on 2026-09-05, so the codebase is receiving commits, but the release cadence is not what you would expect from a project shipping continuously.

Peanut against docker-compose and Testcontainers

The nearest alternative is docker-compose, and the difference is not capability but lifecycle. A compose file declares services up front and brings them up as a group; the ports are fixed in the file, and the containers persist until someone runs down. Peanut inverts that: services are created on request through an HTTP call, ports are assigned by the host and reported back in the configs block, and lifetime is expressed per instance with deleteAfter. If your tests run in parallel and each worker needs its own Redis on its own port, the compose approach forces you to pre-allocate ports per worker, while Peanut hands you a fresh port per request. The trade-off is that compose is declarative and reproducible from the repository alone, whereas Peanut requires a running server, an API key and a network round trip before your test can connect.

Testcontainers takes a third position: the test process itself starts and stops the container through a language-specific library, so there is no central service to operate and no shared state between runs. Peanut centralises instead. That is better when many pipelines across several repositories should share one host and one cleanup policy, and worse when you want the test suite to be self-contained with no external dependency beyond a Docker socket. The README's own comparison is to yaml files, configuration management tools and helm, and it argues for Peanut on size and speed of use rather than on features those tools lack.

A fourth option is simply running the database directly on the build agent. That avoids the network hop and the API key entirely, at the cost of installing and versioning the engine yourself on every agent image.

Maintenance, upgrades and the MIT licence

Peanut is MIT licensed, and the repository carries a LICENSE file at the top level alongside a check_license Make target that enforces a copyright or generated header on Go files. MIT is permissive: you can use, modify and redistribute the code, including in commercial settings, provided the copyright notice and permission notice are retained. That is the extent of what the repository states, and it is not legal advice; if you redistribute Peanut inside a product, have counsel read the actual LICENSE file rather than this summary.

Operationally, the upgrade path is scripted. The README documents deployment/linux/upgrade.sh, run the same way as the installer, and there is an UPGRADE-0.3.0.md file at the repository root, which suggests version-specific migration notes have been published at least once. That is a good sign for anyone running an older install, but it also means you should check for such a file before jumping versions. The Makefile exposes the maintenance surface a contributor would use: install_revive for the linter, style for gofmt checks, check_license, test_short, test and integration, with the integration target explicitly noted as requiring etcd. Running the integration suite therefore needs a live etcd cluster, not just Docker.

The cost of running Peanut is not the binary. It is etcd, Docker and docker-compose on a host you keep alive, plus the operational attention that comes with a stateful service that starts containers on demand. The autoClean setting defaults to true, which means stale images, volumes and networks are removed automatically; on a busy host that is helpful, and on a host where you also run other Docker workloads it is a setting to review before the first deploy.

Editorial conclusion

Adopt Peanut if your team already runs Docker on a shared Linux host and wants ephemeral MySQL, Redis or RabbitMQ instances created from a pipeline step rather than from a checked-in compose file. Skip it if you need Kubernetes-native provisioning, a managed cloud database, or anything with a formal support contract, since the newest release listed is v0.7.0 from 2023-02-23 and the README documents no rollback path for a failed deploy. Before committing, verify that the service you need appears in the supported list, that your host has etcd and docker-compose installed as the Linux deployment section requires, and that the deleteAfter field behaves the way your cleanup job expects.

Frequently asked questions

What is Clivern/Peanut used for?

It deploys and configures commonly used services such as databases, message brokers, caching and tracing tools for development and testing pipelines. The README says it suits cases where mocking is not possible, and it works by driving a containerization runtime like Docker.

How do I install Peanut on Ubuntu?

The README gives a bootstrap script at deployment/linux/install.sh that installs etcd, docker, docker-compose and peanut, and notes a cold start may take a while. Peanut then runs on port 80 with the dashboard at http://<public-ip>, and you set app.hostname in /etc/peanut/config.prod.yml to your public IP or hostname before restarting the service.

Which services does Peanut support?

The README lists MySQL, MariaDB, PostgreSQL, Redis, Etcd, Grafana, Elasticsearch, MongoDB, Graphite, Prometheus, Zipkin, Memcached, Mailhog, Jaeger, RabbitMQ, Consul, Vault, Cassandra, Minio, Docker Registry, Ghost, Httpbin, Nagios and Etherpad.

Does Peanut need etcd and Docker?

Yes. The Linux deployment section instructs you to install an etcd cluster or single node and to install docker and docker-compose, and go.mod depends on go.etcd.io/etcd/client/v3. The Makefile's integration target is also marked as requiring etcd.

Official sources

  1. Clivern/Peanut on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/clivern-peanut.svg)](https://hysenlabs.com/projects/clivern-peanut)