DigitalOcean Marketplace
July 19, 2026 · View on GitHub
Build and submission files for the 1-Click Droplet App (Path B of #72).
Base image: Ubuntu 24.04 LTS (ubuntu-24-04-x64).
Layout
deploy/digitalocean/
├── README.md # this file — build guide + submission checklist
├── manifest.yaml # Vendor Portal form reference
├── assets/
│ └── description-long.md # Marketplace long description
└── droplet/
├── template.pkr.hcl # Packer template (manifest post-processor included)
├── scripts/
│ ├── 01-install.sh # Docker CE + compose plugin, droplet-agent purge, image pre-pull
│ └── 02-configure.sh # UFW, exec bits (MOTD + first-boot!), /app/data, version pinning, application.info
└── files/
├── etc/systemd/system/libredb-studio.service
├── etc/update-motd.d/99-libredb-studio
└── var/lib/cloud/scripts/per-instance/99-libredb-first-boot.sh
DO's official 90-cleanup.sh / 99-img-check.sh are fetched at build time
from digitalocean/marketplace-partners
— they are not vendored here. Both the workflow and the local build pin the
same reviewed commit (the scripts run as root inside the image build); bump
the pin deliberately, in both places, after reviewing upstream changes.
Build
GitHub Actions (recommended): Actions → "DO Packer Build" → Run workflow →
enter a version (semver, e.g. 0.9.59 — must exist as a tag on
ghcr.io/libredb/libredb-studio). The snapshot ID appears in the job summary.
Requires the DIGITALOCEAN_TOKEN repo secret (read+write PAT).
Local:
cd deploy/digitalocean/droplet
MP_SHA=b70878804ca27c01d5f5e882d26485defbaba210 # keep in sync with .github/workflows/do-packer-build.yml
curl -fsSLo scripts/90-cleanup.sh "https://raw.githubusercontent.com/digitalocean/marketplace-partners/${MP_SHA}/scripts/90-cleanup.sh"
curl -fsSLo scripts/99-img-check.sh "https://raw.githubusercontent.com/digitalocean/marketplace-partners/${MP_SHA}/scripts/99-img-check.sh"
export DIGITALOCEAN_TOKEN=dop_v1_...
packer init .
packer validate -var "version=0.9.59" .
packer build -var "version=0.9.59" .
Critical build rules
- Never reboot after
90-cleanup.sh. Cleanup wipes the cloud-init semaphores; a reboot would run the first-boot script on the build droplet and bake generated secrets into the snapshot — every customer would get the same credentials. The flow is always: cleanup → img-check → snapshot. - The first-boot script must be executable. cloud-init silently skips
non-executable files;
02-configure.shguarantees the exec bit — do not remove that line. - The MOTD file must stay extensionless.
run-parts --lsbsysinitsilently ignores files with a.shsuffix. environment_varsis mandatory on every provisioner using${VERSION}. Without it,docker pullandsedsilently run with an empty value./opt/digitaloceanmust not exist in the snapshot —99-img-check.shfails on it;01-install.shpurges the droplet-agent.
Pre-submission checklist
-
packer validate→ clean - Fresh test Droplet from the snapshot ($6) → MOTD shows up
-
http://<IP>:3000loads;/api/db/health→{"status":"ok"} - Login works with the credentials from
/etc/libredb-studio.env - SQLite data survives a Droplet restart (
/app/data) -
ufw status→ active (only 22/tcp LIMIT; port 3000 is published via Docker's iptables rules and intentionally absent from the ufw list) -
cat /root/.ssh/authorized_keys→ empty/missing (remove your test key!) -
bash 99-img-check.shon the Droplet → "0 Tests FAILED" - A "host key changed" SSH warning on first login is expected — cleanup deletes host keys; cloud-init regenerates them
Submission
- Vendor Portal → New App → snapshot ID
- Marketing assets:
- Logo 128×128 PNG
- Screenshots (editor + results grid)
- Short description (≤75 chars):
Open-source SQL IDE with AI — PostgreSQL, MySQL, MongoDB, Redis & more - Long description:
assets/description-long.md
- Follow-up: one-clicks-team@digitalocean.com — there is no official review SLA; a polite nudge after a couple of weeks is fine.
- After approval, add the Marketplace link next to the other one-click buttons in the root README.