Domain Management
Let’s first of all look at how domains work with Bovine Pages Server. There are three main types of domain/URL patters:
URL Patterns
Bovine Pages supports three types of URLs:
1. Repository Sites
https://john.pages.example.com/blog/
- Serves from
john/blog/public/ - One site per repository
- Perfect for project documentation or blogs
2. Profile Sites
https://john.pages.example.com/
- Serves from
john/.profile/public/ - Create a repository called
.profile - Your personal homepage
3. Custom Domains
https://www.yourblog.com/
- Serves from any repository with
custom_domainset - Automatic HTTPS with Let’s Encrypt
Repository and .profile sites will work out the box and depending on the pages domain your admin set up will depend on the final URL you need. Custom domain support allows you to serve your static sites on your own domain names (e.g., www.example.com) instead of or in addition to the default pages domain format. However theres some setup you need to do.
In order to register your custom domain with Bovine you must first browse to your pages repository URL.
Using custom Domains
The implementation uses a registration-based approach where domains are registered when users access their pages URL. All requests remain fast through cache-only lookups with no repository searching. Security is maintained by respecting repository visibility settings and limiting access based on authentication tokens when needed.
Traefik Configuration
Two routers with different priorities handle routing:
- High-priority router (10) handles
*.pages.example.com - Low-priority router (1) catches remaining domains
Traefik automatically provisions SSL certificates for custom domains via configured certificate resolvers. So you get automatic domain registration for your custome domain.
User Setup
Users activate custom domains by:
- Creating a repository with static files in a
public/folder - Adding
custom_domain: www.example.comto their.pagesfile - Configuring DNS records pointing to the Traefik server (you may need to verify your DNS with a txt record)
- Visiting their pages URL to register the domain
- Accessing their custom domain
DNS Verification (Optional)
DNS verification is an optional security enhancement that administrators can enable to verify domain ownership before allowing custom domain registration.
How It Works
When DNS verification is enabled, the system performs a DNS TXT record lookup on the custom domain to confirm ownership. The TXT record must contain a specific verification hash that proves the user owns both the domain and the repository.
Enabling DNS Verification
Administrators can enable this feature by setting enableCustomDomainDNSVerification: true in the middleware configuration. When disabled (default), users can skip the verification step.
User Setup with DNS Verification
When DNS verification is enabled, users must complete these additional steps:
1. Generate Verification Hash
Calculate the SHA256 hash of your repository path in the format owner/repository:
# Example for repository squarecows/bovine-website
echo -n "squarecows/bovine-website" | sha256sum
# Result: 73bb8214899661e7f7900c77714586cc51702e6cf26a58c62e17fa9d88f3d3d3
Alternatively you can use the easy Generator tool hosted here.
2. Create DNS TXT Record
Add a TXT record to your domain with the following format:
TXT www.example.com bovine-pages-verification=73bb8214899661e7f7900c77714586cc51702e6cf26a58c62e17fa9d88f3d3d3
The record pattern is: bovine-pages-verification=<SHA256_HASH>
3. Configure DNS A/CNAME Record
Add your A or CNAME record pointing to the Traefik server:
A www.example.com 192.0.2.1
# or
CNAME www.example.com traefik.example.com
4. Verify DNS Propagation
Before activating, verify your DNS records have propagated:
# Check TXT record
dig TXT www.example.com
# Check A/CNAME record
dig www.example.com
5. Activate Custom Domain
Visit your pages URL to register the domain. The plugin will verify the TXT record on each access.
The TXT record must remain in place for the custom domain to stay active, as verification occurs with each registration refresh.
Branch Subdomains
Branch subdomains allow you to serve content from specific Git branches as subdomains of your custom domain. This is useful for staging environments, QA testing, or previewing feature branches.
How It Works
When you configure branch subdomains:
- The main domain serves content from your default branch
- Branch subdomains serve content from their respective branches
- Git branch names are automatically converted to valid DNS subdomain labels (slashes become hyphens, converted to lowercase)
Configuration
Add enable_branches to your .pages file:
enabled: true
custom_domain: bovine.example.com
enable_branches:
- stage
- qa
- feature/new-design
This configuration results in:
https://bovine.example.com/→ serves from default branchhttps://stage.bovine.example.com/→ serves fromstagebranchhttps://qa.bovine.example.com/→ serves fromqabranchhttps://feature-new-design.bovine.example.com/→ serves fromfeature/new-designbranch
DNS Setup for Branch Subdomains
You need to configure DNS records for each branch subdomain:
# Main domain
A bovine.example.com 192.0.2.1
# Branch subdomains (can use wildcard)
A *.bovine.example.com 192.0.2.1
# Or individual records
A stage.bovine.example.com 192.0.2.1
A qa.bovine.example.com 192.0.2.1
Using a wildcard DNS record (*.bovine.example.com) simplifies setup and allows you to add new branches without updating DNS.
Branch Name Sanitisation
Git branch names are automatically converted to valid DNS subdomain labels:
| Git Branch Name | Subdomain |
|---|---|
stage |
stage.example.com |
feature/login |
feature-login.example.com |
Feature/NEW-Design |
feature-new-design.example.com |
release/v2.0 |
release-v2-0.example.com |
Protecting Branch Subdomains
You can protect branch subdomains with a password while keeping the main site public. See Branch Password Protection for details.
Complete Example
Here’s a complete .pages configuration with branch subdomains and protection:
enabled: true
custom_domain: mysite.example.com
enable_branches:
- stage
- qa
- develop
branchesPassword: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
This gives you:
- Public production site:
https://mysite.example.com/ - Password-protected staging:
https://stage.mysite.example.com/ - Password-protected QA:
https://qa.mysite.example.com/ - Password-protected development:
https://develop.mysite.example.com/