Vendor integration diagrams show everything connected to everything. On dardev-vps we run a smaller honest set: GitLab for source and CI, Portainer for Docker Compose lifecycle on the same host, Grafana plus Prometheus for metrics—not because we lack ambition, but because each connector is ops debt.
This article lists what is production today, how data flows, and what we explicitly do not integrate despite appearing on roadmap slides.
GitLab: source of truth for deployable artifacts
Monorepo dardev-mailer holds news static site, Twenty/Listmonk compose files, sync worker, and deploy scripts. GitLab CI builds container images, runs Python validators for news articles, and triggers deploy jobs over SSH to dardev-vps on protected branches.
- Merge to main → staging or direct prod deploy per service policy
- CI variables hold VPS SSH keys and registry tokens—not committed secrets
- Pipeline badges visible to team; failed news validate blocks merge
- Issue boards track outreach and infra tasks separately from Hesabi product repo
Portainer: Compose stacks we touch weekly
Not every service runs Kubernetes. Portainer manages docker-compose.yml stacks for Twenty, Listmonk, Stalwart, sync worker, and co-hosted properties. Operators restart unhealthy containers, view logs, and pull images after CI push—without SSH memorization for every stack name.
Grafana and Prometheus: metrics we page on
node_exporter on VPS, application /metrics endpoints, and nginx logs inform dashboards described in grafana-dashboards-small-teams. Alerts go to Telegram for disk, error rate, and cert expiry windows—see related guide for panel layout.
How they connect—not a mesh
- Developer pushes
GitLab CI builds and optionally deploys via script to VPS.
- Runtime
Portainer shows container health; operators correlate with Grafana spike.
- Incident
Rollback via git revert plus redeploy script, not mystery Portainer-only state.
Integrations we actually run beyond the title
Twenty CRM webhooks to sync worker to Listmonk—documented in inside-unified-mailer-stack and crm-driven-product-lists. TTN connectivity lives in Hesabi product infrastructure, not on the same Portainer host as marketing mailer. news.dardev.net subscribe API hits sync worker health checks in verify-news.sh.
What we do not claim in production
- EscaHire marketplace integrations—waitlist only
- Bi-directional HubSpot replacement—Twenty plus Listmonk is intentional split
- Full GitOps on every stack—Compose plus Portainer still valid here
- Multi-region active-active—single VPS with backups matches our scale

Why this matters for clients
DarDev Services sells what we run. Client proposals list GitLab CI patterns, Portainer or kubectl ops, and Grafana baselines we reuse—not integrations we plan to build if you sign. Deployed Realities category exists for this honesty.
Tunisia teams often already have GitLab or GitHub; we meet them there instead of mandating greenfield toolchain.
kubectl remains available for lab clusters and client K8s—Portainer does not replace cluster skills, it reduces friction on Compose-heavy VPS.
Windows developers use WSL deploy scripts matching CI—same paths documented in runbooks under scripts/.
Quarterly we audit unused integrations: if no alert fired from a datasource in ninety days, remove it.
Security reviews get list of external webhooks and open ports—integration honesty includes attack surface.
Future additions require runbook before merge—same bar we apply to client hardening engagements.
Access and permissions
GitLab protected branches require MR approval for prod deploy paths. Portainer admin limited to ops rotation—not every developer. Grafana viewers get read-only dashboards for founders; editors are platform owners only.
Separate Hesabi fiscal support from mailer ops escalation—different on-call skills, different secrets.
Common failure modes
- CI deploy succeeds but Portainer shows old image tag—registry cache or wrong compose pull
- Grafana green while app down—health check too shallow
- Manual Portainer env change not in git—drift until next deploy overwrite
- GitLab runner disk full—pipelines fail silently until someone checks
Runbooks document each failure with first command to run—usually git log, docker compose ps, curl health.
Client engagements export this integration pattern as template—customized hostnames, same discipline.
We publish this under Deployed Realities so prospects compare our live stack to marketing claims elsewhere.
Onboarding a new operator
Week one: read-only GitLab access, Grafana viewer, shadow deploy script run. Week two: Portainer log access, rehearse rollback on staging stack. Week three: on-call pairing during low-traffic window—no solo prod keys day one.
Documentation lives in repo runbooks, not Notion alone—if git is down, Notion will not deploy fixes.
Integrations succeed when boundaries are boring: git deploys, Portainer observes, Grafana alerts, humans write runbooks.
Before adding a fourth tool to this stack, ask who maintains it at 2 a.m.—if nobody, defer.
See portainer-vs-kubectl and deployed-realities-explained for related operational context on this site.
Honest integration lists age better than roadmap screenshots—update this article when we add or remove a production connector.
Contact DarDev Services via dardev.net if you want this exact ops trio scoped for your VPS or small cluster deployment.
Fewer moving parts means fewer midnight pages—that is the integration strategy.
Portainer vs kubectl for Compose?
Portainer for daily ops visibility; git plus scripts for intentional changes.
GitLab self-hosted or SaaS?
DarDev uses GitLab compatible remotes; CI patterns transfer.
Grafana without Kubernetes?
Yes—metrics on VPS are our default before cluster complexity.
Can you replicate this stack?
DarDev Services scopes GitLab plus observability setup—contact via dardev.net.
Where to read mailer integrations?
Start with inside-unified-mailer-stack on this site.



