Skip to content

Custom Domains & Ingress Routing

MicroFly natively supports adding and managing custom domains for all your applications—similar to modern cloud platforms like Fermyon Cloud, Fly.io, and Heroku. You can route apex domains, specific subdomains, and wildcard subdomains to any service, complete with automated HTTPS certificate generation, scale-to-zero wakeups, and domain collision protection.


Ingress Architecture

MicroFly delegates public TLS termination to an external reverse proxy (Caddy, Nginx, or Apache) and runs an internal high-speed ingress proxy on loopback (127.0.0.1:8000).

User Request (https://api.mybrand.com)


      DNS Record (A / CNAME) ──► Points to your server's Public IPv4/IPv6


      Reverse Proxy (Caddy / Nginx) ──► Handles TLS & ACME Let's Encrypt Certificates
                 │  (Preserves Host: api.mybrand.com)

      MicroFly Ingress (127.0.0.1:8000) ──► Inspects Host header & resolves to app
                 │  (Buffers request & triggers ~200ms cold start if sleeping)

      Workload Service Instance (127.0.0.1:3000+)

1. Configuring Domains in app.toml

Declare one or more domains in your application's app.toml manifest:

toml
name = "web-api"

# Route single or multiple custom domains to this application:
domain = [
  "mybrand.com",
  "api.mybrand.com",
  "*.staging.mybrand.com"
]

[runtime]
args = ["./bin/server"]
port = 8080

[scale_to_zero]
enabled = true
idle_timeout = "10m"

Supported Domain Formats

FormatExampleBehavior
Apex Domainmybrand.comRoutes requests matching Host: mybrand.com directly to the app.
Subdomainapi.mybrand.comRoutes requests matching Host: api.mybrand.com.
Wildcard Domain*.customers.mybrand.comRoutes any subdomain matching the pattern (e.g. acme.customers.mybrand.com).

2. DNS Configuration

At your DNS registrar or DNS provider (Cloudflare, AWS Route 53, Namecheap, Google Cloud DNS, etc.), configure DNS records pointing to your MicroFly server:

Apex Domain (mybrand.com)

Add an A record for IPv4 and optionally an AAAA record for IPv6:

text
Type: A     Name: @       Value: <YOUR_SERVER_PUBLIC_IP>
Type: AAAA  Name: @       Value: <YOUR_SERVER_IPV6> (optional)

Subdomain (api.mybrand.com)

Add an A record pointing to your server's IP, or a CNAME record pointing to your server's hostname:

text
Type: CNAME Name: api     Value: mybrand.com.
# OR
Type: A     Name: api     Value: <YOUR_SERVER_PUBLIC_IP>

Wildcard Domain (*.mybrand.com)

text
Type: A     Name: *       Value: <YOUR_SERVER_PUBLIC_IP>

The "Zero-DNS" Dokploy Pattern (One-Time Setup)

When deploying multiple microservices, you do not need to create new DNS records or touch your DNS registrar each time a new service is launched:

  1. Configure a single Wildcard DNS record once: Point *.mydomain.com to your server's IP address.
  2. Set default_domain in /etc/microfly/microfly.toml:
    toml
    default_domain = "mydomain.com"
  3. Deploy new apps with arbitrary subdomains on-the-fly:
    bash
    # Assign any custom namespace or random subdomain:
    microfly domains add my-app service-namespace.mydomain.com
    
    # Or auto-generate <app>.mydomain.com:
    microfly domains generate my-app
    Because the * DNS record matches all subdomains, traffic routes to your server immediately with zero DNS reconfiguration and zero propagation wait.

Zero-DNS Setup (Free Wildcard DNS via sslip.io / nip.io)

If you want to test without owning a domain name:

bash
# Point traffic directly using your server's public IP (e.g. 198.51.100.25):
microfly domains add my-app service-namespace.198.51.100.25.sslip.io

Public DNS resolvers automatically resolve *.198.51.100.25.sslip.io to 198.51.100.25, allowing immediate routing with zero DNS configuration anywhere.


3. Automatic TLS / HTTPS Certificates

Like Fermyon Cloud, MicroFly integrates seamlessly with Caddy to provide automated, zero-touch SSL/TLS certificate management via Let's Encrypt and ZeroSSL.

Option A: Static List of Domains (Standard)

In /etc/caddy/Caddyfile, list your custom domains:

caddy
{
    email [email protected]
}

# Automatic TLS for your apex domain and subdomains
mybrand.com, api.mybrand.com, *.staging.mybrand.com {
    reverse_proxy 127.0.0.1:8000 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
    }
}

Caddy automatically provisions, validates, installs, and renews TLS certificates before expiration.

Option B: On-Demand TLS (Dynamic Multi-Tenant Custom Domains)

If you run a SaaS application where your customers point their own arbitrary domains (e.g. store.customerdomain.com) to your server dynamically:

caddy
{
    on_demand_tls {
        # Validates that incoming domain is known and active on MicroFly
        ask http://127.0.0.1:8000/healthz
    }
}

:443 {
    tls {
        on_demand
    }

    reverse_proxy 127.0.0.1:8000 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
    }
}

When a new customer custom domain receives its first HTTPS request, Caddy automatically obtains a certificate on-the-fly from Let's Encrypt.


4. Scale-to-Zero Integration

Custom domains are tightly coupled with MicroFly's scale-to-zero engine:

  1. When your application is inactive, it automatically sleeps (0% CPU, 0 MB RAM).
  2. When an HTTP/HTTPS request arrives on any configured custom domain (e.g. https://api.mybrand.com/users), MicroFly's ingress router intercepts the connection.
  3. MicroFly holds the request in memory, launches the application via systemd in ~200ms, and proxies the request to the new instance as soon as the port responds.
  4. The client receives a fast, seamless response with zero dropped connections.

5. Preview Environments on Custom Domains

When deploying Git branches or pull requests with ephemeral preview environments:

bash
git push production feature/checkout:preview/checkout

MicroFly automatically generates preview domains under each custom domain configured in app.toml:

  • mybrand.com -> preview-checkout.mybrand.com
  • api.mybrand.com -> preview-checkout.api.mybrand.com

6. Domain Collision Protection

MicroFly guarantees domain ownership safety across all deployed applications:

  • If app-a is deployed with domain = ["api.mybrand.com"], and another application app-b attempts to deploy claiming the same domain, MicroFly's pre-flight validation immediately rejects the deployment:
    text
    error: domain api.mybrand.com is already owned by app app-a
  • This prevents accidental traffic hijacking or conflicting ingress routes between teams or projects.

7. Dynamic Domain Assignment via CLI & API

Similar to platforms like Dokploy, Dokku, and Coolify, you can dynamically assign, remove, and auto-generate domains for any running application directly via the CLI or Admin REST API without editing app.toml or triggering a code redeployment.

List Assigned Domains

bash
microfly domains list my-app
# Or shorthand:
microfly domains my-app

Add a Custom Domain Dynamically

bash
microfly domains add my-app api.customdomain.org

MicroFly immediately updates its internal ingress routing table with zero downtime.

Auto-Generate Platform Subdomains (Dokploy "Generate Domain")

In /etc/microfly/microfly.toml, configure a cluster base domain:

toml
default_domain = "apps.mycompany.com"

Then auto-assign a platform subdomain with one command:

bash
microfly domains generate my-app
# Output: generated and assigned domain my-app.apps.mycompany.com to my-app

(If default_domain is not configured, it defaults to <app>.localhost).

Remove a Dynamically Assigned Domain

bash
microfly domains rm my-app api.customdomain.org

(Note: Domains declared directly in app.toml cannot be removed via CLI; update the manifest to change static domains).

Released under the MIT License.