On this page
deployment
introduction
dframework is engineered for raw throughput and low latency execution. for production environments, dframework offers three deployment architectures:
- direct bare metal with native tls (default): single process architecture where the native transport addon handles openssl tls 1.3 termination, http to https redirects, and routing.
- reverse proxy (
--proxy): traditional deployment behind caddy or nginx when sharing ports with other services or integrating with an existing proxy stack. - edge deployment (
--edge): running plain http behind cloudflare or another cdn where tls termination occurs at the edge.
deployment strategies
direct bare metal (default)
in direct bare metal mode, dframework binds port 443 with native openssl tls and simultaneously runs a lightweight listener on port 80 to redirect http traffic to https.
1[ client ] --( https:443 )--> [ dframework ssl app (native tls) ]2[ client ] --( http:80 )----> [ dframework redirect app (301) ]benefits:
- zero reverse proxy overhead (no extra tcp loopback hop or context switching).
- native multi domain sni support via
storage/certs/{domain}/. - single node process running under systemd with non root privileges.
reverse proxy with caddy
in reverse proxy mode, a dedicated web server such as caddy receives public https traffic on port 443 and proxies plain http requests over local loopback (127.0.0.1:825) to dframework.
1[ client ] --( https:443 )--> [ caddy ] --( loopback:825 )--> [ dframework ]when to choose a reverse proxy:
- hosting multiple independent applications on the same server sharing port 80 and 443.
- integrating with existing infrastructure that requires custom proxy middleware or external waf rules.
edge deployment with cloudflare
in edge mode, cloudflare terminates public tls connections and forwards requests to your origin server over http or https.
1[ client ] --( https )--> [ cloudflare edge ] --( http/https )--> [ dframework ]benefits:
- ddos protection and global cdn caching at the edge.
- origin server can run on an internal port with firewall rules restricting access to cloudflare ip addresses.
automated deployment
the dstrn deploy command automates configuration generation, certificate provisioning, and service installation.
direct bare metal setup
to generate bare metal production configuration for your domain:
1dstrn deploy --domain=api.example.com --email=admin@example.com
for multi domain setups, provide comma separated domains:
1dstrn deploy --domain=api.example.com,admin.example.com --email=admin@example.com
this command performs the following actions:
- verifies or generates a production
APP_KEYin.env. - checks for existing certificates in
storage/certs/{domain}/and obtains missing certificates. - creates
deploy/dframework-<app>.servicewithAmbientCapabilities=CAP_NET_BIND_SERVICEso the application can bind ports 80 and 443 without root privileges. - creates
deploy/dframework-<app>-renew.timeranddeploy/dframework-<app>-renew.serviceto automate weekly certificate renewal.
reverse proxy setup
to generate caddy and systemd service configurations:
1dstrn deploy --proxy --domain=api.example.com
this generates:
deploy/Caddyfilewith reverse proxy rules pointing to your application port.deploy/dframework-<app>.serviceconfigured for standard unprivileged execution.
edge setup
to generate systemd service files with cloudflare guidance:
1dstrn deploy --edge --domain=api.example.com
dry run preview
preview all generated service and configuration files in the terminal without writing to disk:
1dstrn deploy --domain=api.example.com --email=admin@example.com --dry-run
system installation
when running on your server with root privileges (sudo), dstrn deploy can write directly to /etc/systemd/system/ and activate the services:
1sudo dstrn deploy --domain=api.example.com --email=admin@example.com --install
manual deployment setup
if you prefer manual server provisioning or are using automation tools, follow these steps.
manual direct bare metal
place your ssl certificate and private key in the application storage directory:
1storage/certs/api.example.com/2 cert.pem3 key.pemconfigure production environment variables in .env:
1APP_ENV=production2APP_DEBUG=false3APP_URL=https://api.example.com4APP_KEY=your_64_character_hex_keycreate /etc/systemd/system/dframework.service:
1[Unit]2Description=dframework application server3After=network.target4 5[Service]6Type=simple7User=user8WorkingDirectory=/var/www/app9ExecStart=/usr/bin/node dstrn serve10Restart=always11RestartSec=312Environment=NODE_ENV=production13AmbientCapabilities=CAP_NET_BIND_SERVICE14 15[Install]16WantedBy=multi-user.targetenable and start the service:
1sudo systemctl daemon-reload2sudo systemctl enable dframework3sudo systemctl start dframework
manual caddy reverse proxy
install caddy on debian or ubuntu:
1sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl2curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg3curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list4sudo apt update5sudo apt install caddyconfigure /etc/caddy/Caddyfile:
1api.example.com {2 reverse_proxy 127.0.0.1:8253}reload caddy:
1sudo systemctl reload caddycaddy will automatically obtain let's encrypt certificates for api.example.com, manage renewals, and proxy requests over loopback to dframework.
tls and certificate management
automatic certificate discovery
dframework automatically detects certificates in storage/certs/ upon startup:
1storage/certs/2 api.example.com/3 cert.pem (or fullchain.pem, certificate.crt, api.example.com.crt)4 key.pem (or privkey.pem, private.key, api.example.com.key)5 ca.pem (optional intermediate chain)6 admin.example.com/7 cert.pem8 key.pemwhen valid certificates are found and APP_URL starts with https://, dframework automatically boots with native openssl tls on port 443 and starts the http to https redirect listener on port 80.
certificate management commands
the dstrn cert command family provides management over the certificate lifecycle.
obtain certificates
obtain a new let's encrypt certificate for one or more domains:
1dstrn cert:obtain --domain=api.example.com --email=admin@example.com
test certificate generation with `--staging` before production issuance to avoid hitting let's encrypt rate limits during deployment validation.
1dstrn cert:obtain --domain=api.example.com --email=admin@example.com --staging
renew certificates
renew all certificates that expire within 30 days:
1dstrn cert:renew --domain=api.example.com --email=admin@example.com
inspect certificate status
check expiration dates, issuer information, and validity for all installed certificates:
1dstrn cert:status
multi domain and sni routing
the transport supports server name indication (sni). when multiple domain directories exist in storage/certs/, each domain receives its matching certificate during the tls handshake.
pair this with domain route groups in your application routes:
1Route.domain('api.example.com', (api) => {2 api.get('/status', async () => json({ service: 'api' }));3});4 5Route.domain('admin.example.com', (admin => {6 admin.get('/status', async () => json({ service: 'admin' }));7});
http to https redirection
when tls is enabled, dframework automatically starts a native non ssl listener on port 80. any request to http://domain/path receives an immediate 301 Moved Permanently response pointing to https://domain/path.
to disable the redirect listener, set tls.redirect: false in config/app.js or TLS_REDIRECT=false in .env.
websocket secure connections
automatic wss promotion
the client automatically promotes websocket connections to wss:// whenever the page is loaded over https://.
because the initial page request is redirected from http to https, the browser always loads over https: and establishes a secure wss:// connection.
native websocket upgrades
on the server side, websocket connections over port 443 are handled directly inside the ssl event loop. the http upgrade handshake occurs over the existing encrypted tls connection, ensuring zero plaintext exposure and instant websocket availability.
systemd service setup
application service unit
the production systemd unit file (/etc/systemd/system/dframework.service):
1[Unit]2Description=dframework application server3After=network.target4 5[Service]6Type=simple7User=ubuntu8WorkingDirectory=/var/www/app9ExecStart=/usr/bin/node dstrn serve10Restart=always11RestartSec=312Environment=NODE_ENV=production13AmbientCapabilities=CAP_NET_BIND_SERVICE14 15[Install]16WantedBy=multi-user.target`AmbientCapabilities=CAP_NET_BIND_SERVICE` allows the systemd service to bind privileged low ports (80 and 443) while running under an unprivileged user account.
certificate renewal timer unit
automated certificate renewal uses a weekly systemd timer (/etc/systemd/system/dframework-renew.timer):
1[Unit]2Description=certificate renewal timer for dframework3 4[Timer]5OnCalendar=weekly6RandomizedDelaySec=36007Persistent=true8 9[Install]10WantedBy=timers.targetwith the corresponding oneshot renewal service (/etc/systemd/system/dframework-renew.service):
1[Unit]2Description=certificate renewal for dframework3 4[Service]5Type=oneshot6WorkingDirectory=/var/www/app7ExecStart=/usr/bin/node dstrn cert:renew --domain=api.example.com --email=admin@example.com8ExecStartPost=/bin/systemctl restart dframeworkenable the renewal timer with:
1sudo systemctl daemon-reload2sudo systemctl enable dframework-renew.timer3sudo systemctl start dframework-renew.timer
environment configuration
standard production .env configuration:
1APP_NAME=dframework2APP_ENV=production3APP_DEBUG=false4APP_URL=https://api.example.com5APP_KEY=your_generated_64_character_hex_key6ACME_EMAIL=admin@example.comoptional explicit tls configuration (overrides auto discovery convention):
1TLS_CERT=storage/certs/api.example.com/cert.pem2TLS_KEY=storage/certs/api.example.com/key.pem3TLS_CA=storage/certs/api.example.com/ca.pem4TLS_REDIRECT=true
performance considerations
traditional architectures place a reverse proxy like caddy or nginx in front of application runtimes. in benchmark measurements, a reverse proxy layer can potentially add over 60% of overhead for simple routes due to double socket buffering, process context switching, and loopback tcp serialization.
direct bare metal deployment eliminates intermediate proxy layers, delivering maximum throughput directly to the application event loop while maintaining automated let's encrypt certificate management and multi domain support.

