Skip to content

Multi-Site Hosting on a Single VPS ​

Learn how epd lets you run multiple independent applications on a single $5 VPS without port collisions, conflicting SSL certificates, or downtime.


The Problem with Other Deployment Tools ​

Many deployment tools (like Kamal or basic Docker Compose setups) assume that one application owns the host's ports 80 and 443.

When you try to deploy a second application on the same machine:

  • The second proxy container fails to bind to port 80/443.
  • Or you have to manually configure an external Nginx or Traefik reverse proxy outside of your deployment tooling.
  • SSL certificates for different domains collide.

How EPD Solves Multi-Site Hosting ​

epd provisions a single, shared Traefik proxy on the host. Every application deployed with epd writes its own isolated dynamic routing file:

/var/lib/epd/proxy/dynamic/
├── blog.yml            # Managed by App 1 (blog.example.com)
├── store.yml           # Managed by App 2 (store.example.com)
└── docs.yml            # Managed by App 3 (docs.example.com)

Each app specifies its own domains and routes in its own epd.yml. When you deploy blog:

  1. epd only updates /var/lib/epd/proxy/dynamic/blog.yml.
  2. Traefik hot-reloads the changes in milliseconds.
  3. store and docs remain completely unaffected!

Example: Deploying Two Apps to One Server ​

App 1: Blog (epd.yml) ​

yaml
name: blog
mode: docker
image: my-dockerhub-user/blog

servers:
  web:
    hosts: [203.0.113.10]
    port: 3000
    domains: [blog.example.com]

proxy:
  email: admin@example.com

App 2: Store (epd.yml) ​

yaml
name: store
mode: process

process:
  install: bun install
  build: bun run build
  start: bun run start

servers:
  web:
    hosts: [203.0.113.10]
    port: 4000
    domains: [store.example.com]

proxy:
  email: admin@example.com

Both apps can be deployed, updated, or rolled back independently.


Isolated Decommissioning ​

If you ever want to permanently decommission an app:

bash
cd my-store-repo
epd remove

epd remove:

  • Stops and removes all containers or PM2 processes for store.
  • Deletes /var/lib/epd/proxy/dynamic/store.yml.
  • Traefik ceases routing traffic for store.example.com.
  • blog and all other applications continue running without interruption.

Next Steps ​

Released under the MIT License.