Domain and Hostname Configuration¶
This guide explains how to configure custom domains, subdomains, and SSL certificates for your Hop3 applications.
Overview¶
An app's hostnames drive the domain(s) it responds to. You can manage them in two equivalent ways:
- The first-class
hop3 domaincommand group (add,remove,set,list,clear). - The
HOST_NAMEenvironment variable, which thedomaincommands write under the hood.
When hostnames are set, Hop3 automatically:
- Configures the reverse proxy (Nginx/Caddy/Traefik) with the appropriate virtual host settings
- Requests and manages SSL/TLS certificates (Let's Encrypt via certbot when the engine is configured, otherwise self-signed)
- Sets up HTTP to HTTPS redirection
Quick Start¶
Set a custom domain for your app:
# Set the hostname
hop3 domain set --app myapp myapp.example.com
# Apply the change (HOST_NAME affects proxy config, so a redeploy is needed)
hop3 deploy --app myapp
Your app is now accessible at https://myapp.example.com (assuming DNS is configured).
Configuration Options¶
Single Domain¶
Multiple Domains¶
Pass several hostnames to serve more than one domain:
Both domains will point to the same application with the same SSL certificate. To add a hostname without replacing the existing list, use hop3 domain add --app myapp <host>; to drop one, use hop3 domain remove --app myapp <host>.
Inspecting and Clearing Domains¶
# List the hostnames currently bound to an app
hop3 domain list --app myapp
# Remove all hostnames (unsets HOST_NAME)
hop3 domain clear --app myapp
Using hop3.toml¶
You can declare an app's hostnames in its hop3.toml using the first-class [domains] section, which translates to HOST_NAME at deploy time:
Or for multiple domains:
By default the listed domains are treated as defaults (existing hostnames are kept). Set _policy = "override" to update HOST_NAME on every deploy.
Setting HOST_NAME directly under [env] also works, but it is mutually exclusive with [domains] — declare hostnames in one place or the other, not both.
No Domain (Direct Port Access)¶
If you don't set any hostname, your app won't get a reverse proxy configuration. It will only be accessible via its direct port (useful for internal services):
DNS Configuration¶
Before Hop3 can serve your application on a custom domain, you must configure DNS to point to your server.
A Record¶
Create an A record pointing to your server's IP address:
Wildcard DNS (Development/Staging)¶
For development environments, you can use wildcard DNS to automatically route all subdomains:
This allows *.example.com to resolve to your Hop3 server, so app1.example.com, app2.example.com, etc. all work automatically.
Local Development with Wildcard¶
For local testing, you can use services like:
- hop3.dev domain (if configured for development)
- nip.io:
myapp.127.0.0.1.nip.ioresolves to127.0.0.1 - sslip.io:
myapp.192.168.1.100.sslip.ioresolves to192.168.1.100 - dnsmasq: Configure local wildcard DNS
Example using nip.io for local testing:
SSL/TLS Certificates¶
Automatic Certificates (Let's Encrypt)¶
Hop3 uses pluggable TLS issuance engines. When the certbot engine is configured on the server (ACME_ENGINE=certbot with ACME_EMAIL set) and you bind a valid public domain, Hop3 automatically:
- Requests a certificate from Let's Encrypt via certbot's webroot challenge
- Configures the reverse proxy to use HTTPS
- Sets up automatic certificate renewal
- Redirects HTTP traffic to HTTPS
If the certbot engine cannot issue a certificate for a public domain, issuance fails loudly rather than silently falling back to a self-signed certificate. When no ACME engine is configured, Hop3 issues a self-signed certificate instead (see below).
Certificate Requirements¶
For automatic certificates to work:
- Domain must resolve to your Hop3 server's public IP
- Port 80 must be accessible (for ACME HTTP-01 challenge)
- Domain must not be a local/private address
Self-Signed Certificates¶
For internal or development deployments where Let's Encrypt isn't available, Hop3 uses self-signed certificates. This happens automatically when:
- Using the special
_(underscore) hostname - Using local/private IP addresses
- Let's Encrypt requests fail
Certificate Status¶
Check certificate status:
# View app status (includes the app's URL)
hop3 app status --app myapp
# Check certificate files directly on the server (per-app cert/key)
ls /home/hop3/nginx/myapp.crt /home/hop3/nginx/myapp.key
Special Hostname Values¶
Catch-All (_)¶
Use the underscore hostname to create a catch-all application that responds to any hostname not matched by other apps:
The catch-all _ must be the sole hostname — it cannot be combined with other domains.
This is useful for:
- Default landing pages
- Development environments
- Applications that handle their own routing
Note: Catch-all apps receive self-signed certificates (browsers will show warnings).
Empty/Unset¶
If no hostnames are set (HOST_NAME empty or unset):
- No reverse proxy configuration is created
- App is only accessible via direct port
- No SSL certificate is provisioned
This is appropriate for:
- Internal microservices
- Background workers
- Apps behind a separate load balancer
Reverse Proxy Backends¶
Hop3 supports multiple reverse proxy backends. The configuration syntax is the same regardless of which proxy you use.
| Proxy | Configuration File Location | Notes |
|---|---|---|
| Nginx | /home/hop3/nginx/ |
Default, most tested |
| Caddy | /home/hop3/caddy/ |
Automatic HTTPS |
| Traefik | /home/hop3/traefik/ |
Container-native |
The proxy is selected during server installation. All proxies support:
- Multiple hostnames per app
- Automatic SSL via Let's Encrypt
- HTTP to HTTPS redirection
- WebSocket proxying
Troubleshooting¶
Domain Not Resolving¶
-
Verify DNS propagation:
-
Check that DNS points to correct IP:
-
Ensure the hostnames are set correctly:
SSL Certificate Issues¶
-
Check certificate status:
-
Review the server's health and TLS engine:
-
Review certbot's logs on the server (Hop3 invokes certbot with its own directories under
/home/hop3/certbot/):
Proxy Not Updating¶
After changing an app's hostnames:
-
Redeploy the application (a hostname change affects the proxy config, so a restart alone is not enough):
-
If issues persist, reload the proxy:
Multiple Apps, Same Domain¶
Only one app can use a specific hostname. If you get errors about duplicate hostnames:
-
List all apps, then inspect the domains of a candidate:
-
Remove the conflicting hostname from the other app:
Examples¶
Production Setup with www Redirect¶
# Configure both domains
hop3 domain set --app myapp example.com www.example.com
hop3 deploy --app myapp
Staging Environment¶
# Use subdomain for staging
hop3 domain set --app myapp-staging staging.example.com
hop3 deploy --app myapp-staging
Multi-Tenant Application¶
For applications that handle multiple customer domains:
# Set primary domain for the app
hop3 domain set --app myapp app.example.com
# Application code handles tenant routing via request headers
# Example: customers access customer1.app.example.com, customer2.app.example.com
Use wildcard DNS (*.app.example.com) and let your application handle tenant routing internally.
Internal Service (No Public Access)¶
# Don't set any hostname - app accessible only via its port
hop3 app start --app internal-api
# Look up the assigned port
hop3 app status --app internal-api
Best Practices¶
-
Always use HTTPS in production: Bind a real public hostname to enable automatic SSL.
-
Use descriptive subdomains:
api.example.com,admin.example.com,staging.example.commake it clear what each service does. -
Keep www redirects: If you use
example.com, also includewww.example.comto handle both. -
Test DNS before deploying: Verify DNS propagation before configuring the hostname in Hop3.
-
Monitor certificate expiry: While Hop3 handles renewal, monitor for failures in production.
Related Guides¶
- User Guide - General application deployment
- Configuration Reference - hop3.toml options
- Administration Guide - Server-level configuration