Self-hosted deployments for fast teams

One Command. Ship.

pl up builds your checkout in a sealed sandbox, puts it on your own servers behind a private network, and hands back an HTTPS address. No pipeline to write. No platform bill.

Deploy your first app → See the topology in 3D →
DeployLoginDomainsTeardown
View the manual ↗
$ pl up
Copy
Live board · demo-app / previewGen 2
Time
Step
Status
00:00
source verified · sha256
BOARDED
00:41
rootless build · fsn1-b1
PUSHED
00:52
network admitted · evidence
CLEARED
01:07
web · healthy · gen 2
AIRBORNE
01:12
https://demo--app.pushleft.dev
LIVE
demo-app — pl
$ pl up, followed by the deployment's events, ending with the live URL.
~/demo-app ❯ ▌
Every branch has a destination
feature/*Preview

Its own URL for dev, test and QA. Share the link, get feedback, merge.

checkout-v2--app.pushleft.dev
developIntegration

Built and tested on every push, on a network of its own.

test-app.example.com
release/*Release

Shipped to end users, with the previous release kept warm.

release-1-8--app.pushleft.dev
mainProduction

Shipped to prod on merge. Health-checked before it takes traffic.

app.example.com

Ship to a server you own.

Your code · your servers · one command

Runs on
How it works

From push to live in five steps.

Push a branch and Pushleft does the rest: builds it, finds it a server, gives it a private network, puts it behind HTTPS, and cleans up after you. You never write the pipeline.

Read the full sequence →
[01]
/ build
Your checkout is built in a sealed sandbox on a build server. It never sees the host, its Docker socket or its secrets.
[02]
/ place
A server with room for it is picked for you. No YAML, no node labels, no capacity spreadsheet.
[03]
/ network
The environment gets its own private network and firewall before anything starts listening.
[04]
/ serve
Containers start with limits and a health check. Traffic switches only once the new release is healthy, and the old one drains out.
[05]
/ retire
Tear it down and everything goes: routes, containers, network. The history stays, so you can always see what ran and when.
0S60S120S180S240S300S360S 1s · database, binaries, registry, Caddy, mTLS material · 6s7s · production-auth API behind the TLS proxy; bootstrap owner · 2s9s · fleet: one build node, one application node · 0s9s · ordinary web-only checkout · 0s9s · pl up, following events · 12s21s · restart replay: kill agent and scheduler, nothing recreated · 13s34s · second release with a crash mid-rollout, same container adopted · 71s105s · tenant isolation: another organization's token · 1s106s · viewer cannot pl up; revoked token fails · 0s106s · failed build: broken Dockerfile · 44s150s · failed start: process exits at once, no route · 73s223s · failed health: /healthz 500, no route · 72s295s · route refused: hostname collision across organizations · 13s308s · tampered source refused by the gateway · 35s343s · custom domain: DNS ownership, ACME, HTTPS, removal · 31s374s · pl down: routes, containers, network, destroyed · 7s381s · pl up again: new network, new subnet slot · 6s SECOND RELEASE WITH A CRA… · 71S FAILED BUILD · 44S FAILED START · 73S FAILED HEALTH · 72S TAMPERED SOURCE REFUSED B… · 35S CUSTOM DOMAIN · 31S 17 STEPS · 387 S · COLOUR = TIME SPENT · HOVER A SEGMENT
The pitch

Own the whole runway.

A deployment platform you install, not rent. The ease of a hosted platform, on servers you already pay for.

One command
1

pl up takes a checkout to an HTTPS address. Nothing to set up first, nothing to keep in sync later.

Pipelines to write
0

No YAML, no runners, no deploy keys to babysit. The platform is the pipeline.

Yours
100%

Your servers, your database, your domain. The only bill is the server bill.

Cost

Pay for servers, not for usage.

Hosted platforms charge per seat, per build minute, per gigabyte, per region. Pushleft charges nothing. You pay your server provider, and that bill is the same whether two people push or twenty.

A parody banknote in engraved bank-note style, denomination one command, issued by the United Bank of Pushleft
Bills
1

Your server provider's. There is no second invoice: nothing from us, no marketplace, no add-on store.

The whole thing, on one box
4vCPU · 8 GB

The full demo ran on one machine of that size: control plane, build node, apps, private network, HTTPS. Hetzner's smallest plans start below it.

Platform fee
€0forever

Open source. No licence, no usage meter, no sales call to unlock a feature you already run.

What you get

Everything between push and live.

01

A URL for every branch

Each branch gets its own address on its own private network. Share the link, get feedback, merge.

02

Rollbacks in seconds

The previous release is kept warm. Going back is one command, no rebuild.

03

Private by default

Each environment runs on its own private network. Only the edge faces the internet.

04

Your domain, HTTPS included

Point your DNS at it. The certificate is issued and renewed for you.

05

Backups and failover built in

Point-in-time restore and a standby control plane come with the install, not as add-ons.

06

Open source, self-hosted

Read it, fork it, run it on the cheapest server that fits. Add servers when you outgrow it.

Who it is for

Built for small teams with big launches.

For teams that would rather ship than run a platform team. One person installs it in an afternoon. Everyone else just pushes.

The founder

One server, a product live tonight, and the same tooling when it is ten servers.

The agency

Every client in its own organisation, on its own network and domain. One console for all of them.

The platform team

Give the company pl up instead of a ticket queue, on servers you already own.

AGENT network.rs: 2200 linesdatabase.rs: 1760 linesbackup.rs: 1426 linesmain.rs: 1201 linesbuild.rs: 1114 linesapplication.rs: 806 linesroutes.rs: 600 linesvolumes.rs: 452 linesfirewall.rs: 450 linesingress.rs: 436 linesenroll.rs: 424 linesruns.rs: 423 linestelemetry.rs: 343 linesupdate.rs: 291 linessecrets.rs: 2 lines API main.rs: 2546 linesauth.rs: 1263 linesauth_tests.rs: 941 linesauth_hardening.rs: 908 linesauth_hardening_tests.rs: 843 linessource/tests.rs: 448 linesrelease_tests.rs: 358 linessource/claims.rs: 247 linessource.rs: 217 linesdomains.rs: 216 linesoperator.rs: 128 lines AGENT-GATEWAY main.rs: 1375 linesenroll.rs: 992 linesapplications.rs: 974 linesingress_tests.rs: 736 linesbuild.rs: 504 linesingress.rs: 499 linessource_tests.rs: 394 linesdurability.rs: 376 linesnetwork_teardown_tests.rs: 332 linesauthorization_tests.rs: 310 linessource.rs: 214 linesruns.rs: 145 linespki.rs: 143 linesnetwork_teardown.rs: 77 lines MESH topology_tests.rs: 1159 linesruntime.rs: 1090 linescontroller.rs: 1006 linesenrollment.rs: 875 linescaddy.rs: 513 linescontroller_route_tests.rs: 479 linesroutes.rs: 464 linestopology.rs: 419 linesmain.rs: 298 linescredential_publication.rs: 166 lineslib.rs: 8 lines SCHEDULER main.rs: 836 linesapplication_tests.rs: 650 linesapplications.rs: 442 linesreclaim.rs: 418 linesretention_tests.rs: 417 linesingress.rs: 374 linesretention.rs: 334 linesdomains_tests.rs: 330 linesdurability.rs: 311 linesreclaim_tests.rs: 302 linesdns.rs: 299 linesdomains.rs: 281 linesdurability_tests.rs: 221 linesingress_tests.rs: 218 linesnetwork_teardown_tests.rs: 195 linesbuild_tests.rs: 178 linesruns.rs: 162 linesnetwork_teardown.rs: 107 linesbuilds.rs: 92 lines CORE database.rs: 786 linesapplication.rs: 728 linesnetwork.rs: 697 linesmanifest.rs: 518 linesdns.rs: 438 linesvolume.rs: 398 linesfirewall.rs: 355 linesingress.rs: 352 linesplan.rs: 283 linesobservability.rs: 137 lineslib.rs: 118 lines CONTROLLER main.rs: 1446 linesfleet.rs: 1020 linesca.rs: 369 linesca_tests.rs: 171 lines OPENPROVIDER lib.rs: 1132 lines SOURCE lib.rs: 618 linestests.rs: 397 lines CLI main.rs: 982 lines HETZNER lib.rs: 940 lines TELEMETRY-GATEWAY main.rs: 923 lines CLOUDFLARE lib.rs: 498 lines OPS lib.rs: 229 lines SECRETS lib.rs: 191 lines
Safety

Built to refuse the wrong thing.

Most outages start with a system saying yes when it should have said not yet. Pushleft says not yet. The worst case is a delay, never a breach.

Gate
Answer
No traffic before health. A new release gets the URL only after it has passed its health check.
HOLD
Free is not the same as allowed. A server having room is not permission to run there. The network has to admit the app first.
HOLD
Nothing is erased. Every status is kept and no network address is reused, so you can always see what happened.
KEPT
Missing a requirement? It stops. If a server cannot enforce the firewall, the deploy is refused rather than run unprotected.
REFUSED

Your code is ready to board.

Open source. Your servers, your database, your domain. The manual takes you from nothing to a live URL on one machine in an afternoon.

Deploy now → Read the manual →
Bored? Mush and Billo are collecting coins and fighting off invaders.
Play →