sucipto
Hi all, I want to show off a project I’ve been building: Bundar.
What it is: a push-to-deploy platform. You bring your own server (any VPS), connect it, and then:
git push bundar main
→ container image built
→ health checks
→ live, zero downtime
Push-to-deploy, health-checked deploys, automatic HTTPS. You can try it for free — point it at a VPS and push.
Why it’s an Elixir story. The whole control plane is a Phoenix app, and Elixir is doing the heavy lifting:
- Phoenix LiveView — the entire dashboard. Deploy logs, server status, service config, all live.
- Postgres — the source of truth for servers, services, and deploy state.
- Oban (free version) — the deploy and provisioning pipeline. One deploy fans out into Oban jobs: build the image, roll it out, run health checks, clean up. Server onboarding is jobs too (install Podman, configure firewalld, set up the reverse proxy, configure sshguard), plus a scheduled ping job that watches every server’s health.
- PUI — our own LiveView UI toolkit, extracted from building this dashboard and open-sourced on Hex (MIT): pui | Hex . The whole UI is built on it.
- NimblePublisher — powers the blog (bundar.dev/blog)
A couple of implementation details that might interest folks here:
- SSH client, forked from librarian. The management plane is SSH hub-and-spoke — the control plane talks to customer servers over Erlang’s
:ssh. The client started as librarian, which we forked and later ported in-app (SSHClient) so we could evolve it alongside Bundar: streaming command output as anEnumerable, connection/identity handling, and SSH tunneling, which we use when setting up the reverse proxy on a fresh server. - Remote curl as a Req adapter. Some HTTP calls need to happen on the server itself (registries, local endpoints), not from the control plane. So we wrote a custom
Reqadapter: the app builds a request with the normal Req API, and the adapter translates it into acurlcommand, executes it remotely over SSH, then parses the rawcurl -ioutput back into a%Req.Response{}. The rest of the codebase never knows the request physically ran somewhere else. - Containers run under Podman with
--userns=auto, so container root maps to an unprivileged host UID. We’re writing about the Podman isolation model on our blog: https://bundar.dev/blog - Caddy for reverse proxy / load balancer. Each server runs a Caddy container (
bundar_proxy) provisioned by an Oban job, and routes are configured dynamically through Caddy’s admin API — which is exactly what the remote-curl Req adapter talks to, over the SSH tunnel.
A note on how it was built. I started learning Elixir & Phoenix in April 2023, and this side project began around October 2023 — before agentic coding was a thing. I bought the bundar.run domain in February 2024 (it expired in February 2026, so now we’re on bundar.dev). These days AI agents help me move a lot faster, but I still review and test everything manually.
One question for the forum. No plans to open-source Bundar for now, but self-hosting is a real possibility down the road. I’d love advice on the best way to ship a compiled release with feature flags — e.g. a self-hosted build with the billing, blog, and landing page modules stripped out. Application env + compile-time config? Runtime feature flags? Something else entirely? Curious how others have done this with mix release.
I’d love feedback — especially from anyone running Oban pipelines in production, or building LiveView dashboards. What would you want to see next? Happy to answer questions about the stack.
Thanks for reading!
Trending in Announcing
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #ai
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #security
- #metaprogramming










