# Service Domain Configuration Standard Standard pattern for domain configuration in rick-infra service roles. ## Architecture Philosophy Rick-infra follows a **direct domain specification** pattern for service configuration: ```yaml # Direct and explicit service_domain: "subdomain.jnss.me" # NOT this (complex and inflexible) service_subdomain: "subdomain" service_domain: "{{ caddy_domain }}" service_full_domain: "{{ service_subdomain }}.{{ service_domain }}" ``` ## Benefits 1. **Simplicity**: One variable instead of three 2. **Flexibility**: Can use any domain (subdomain, root, or completely different) 3. **Explicitness**: Clear what domain the service uses 4. **No Forced Inheritance**: Not tied to infrastructure `caddy_domain` 5. **Consistency**: All services follow the same pattern --- ## Standard Pattern ### Basic Service (Single Domain) For services that only need one domain: ```yaml # roles/service/defaults/main.yml service_domain: "service.jnss.me" # host_vars/host/main.yml (explicit override) service_domain: "service.jnss.me" ``` **Examples:** - Authentik: `authentik_domain: "auth.jnss.me"` - Nextcloud: `nextcloud_domain: "cloud.jnss.me"` ### Advanced Service (Multiple Domains) For services that need separate domains for different purposes: ```yaml # roles/service/defaults/main.yml service_http_domain: "service.jnss.me" # Web interface service_api_domain: "api.jnss.me" # API endpoint service_ssh_domain: "jnss.me" # SSH/CLI operations # host_vars/host/main.yml (explicit override) service_http_domain: "service.jnss.me" service_api_domain: "api.jnss.me" service_ssh_domain: "jnss.me" ``` **Example:** - Gitea: - `gitea_http_domain: "git.jnss.me"` (web interface) - `gitea_ssh_domain: "jnss.me"` (Git operations) --- ## Usage in Templates ### Caddy Configuration ```jinja # roles/service/templates/service.caddy.j2 {{ service_domain }} { reverse_proxy 127.0.0.1:{{ service_port }} } ``` ### Application Configuration ```jinja # roles/service/templates/service.conf.j2 [server] DOMAIN = {{ service_domain }} ROOT_URL = https://{{ service_domain }}/ ``` ### Task Display Messages ```yaml # roles/service/tasks/main.yml - name: Display service information debug: msg: | 🌐 Web Interface: https://{{ service_domain }} 📍 Access your service at the domain above ``` --- ## Domain Selection Guidelines ### Use Root Domain When: - Service is the primary purpose of the infrastructure - You want cleaner URLs (e.g., SSH: `git@jnss.me` vs `git@git.jnss.me`) - Industry standard uses root domain (e.g., GitHub uses `github.com` for SSH) ### Use Subdomain When: - Service is one of many - You want explicit service identification - You need clear separation between services ### Use Different Domain When: - Service needs to be on a different apex domain - External service integration requires specific domain - Multi-domain setup for geographical distribution --- ## Examples by Service Type ### Identity/Auth Service ```yaml authentik_domain: "auth.jnss.me" ``` **Rationale**: Auth subdomain is an industry standard ### Storage Service ```yaml nextcloud_domain: "cloud.jnss.me" ``` **Rationale**: "cloud" clearly indicates storage/sync service ### Git Service ```yaml gitea_http_domain: "git.jnss.me" # Web UI gitea_ssh_domain: "jnss.me" # SSH operations ``` **Rationale**: - HTTP uses `git.` for clarity - SSH uses root domain to avoid `git@git.jnss.me` redundancy - Matches GitHub/GitLab pattern ### Monitoring Service ```yaml grafana_domain: "monitor.jnss.me" prometheus_domain: "metrics.jnss.me" ``` **Rationale**: Different subdomains for different monitoring tools --- ## Configuration Layers ### 1. Role Defaults (`roles/service/defaults/main.yml`) Provide sensible defaults: ```yaml # Option A: Use specific domain (explicit) service_domain: "service.jnss.me" # Option B: Use caddy_domain if it makes sense (flexible) service_domain: "service.{{ caddy_domain | default('localhost') }}" # Recommendation: Use Option A for clarity ``` ### 2. Host Variables (`host_vars/hostname/main.yml`) **Always explicitly set** in production: ```yaml # ================================================================= # Service Configuration # ================================================================= service_domain: "service.jnss.me" ``` **Why explicit?** - Clear what domain is configured - Easy to change without understanding defaults - Easier to audit configuration - Documentation in configuration itself ### 3. Group Variables (`group_vars/production/main.yml`) For settings shared across production hosts: ```yaml # Common production settings service_enable_ssl: true service_require_auth: true # Generally avoid setting domains in group_vars # (domains are usually host-specific) ``` --- ## Anti-Patterns to Avoid ### ❌ Subdomain Composition ```yaml # DON'T DO THIS service_subdomain: "service" service_domain: "{{ caddy_domain }}" service_full_domain: "{{ service_subdomain }}.{{ service_domain }}" ``` **Problems:** - Complex (3 variables for 1 domain) - Inflexible (can't use root or different domains) - Forces inheritance from infrastructure variable - Inconsistent with other services ### ❌ Implicit Inheritance ```yaml # DON'T DO THIS service_domain: "{{ caddy_domain }}" ``` **Problems:** - Not explicit what domain is used - Harder to change - Hides actual configuration - Requires understanding of infrastructure variables ### ❌ Mixed Patterns ```yaml # DON'T DO THIS authentik_domain: "auth.jnss.me" # Direct nextcloud_subdomain: "cloud" # Composition service_domain: "{{ caddy_domain }}" # Inheritance ``` **Problems:** - Inconsistent - Confusing for maintainers - Different patterns for same purpose --- ## Migration from Old Pattern If you have services using the old subdomain composition pattern: ### Step 1: Identify Current Variables ```yaml # Old pattern service_subdomain: "service" service_domain: "{{ caddy_domain }}" service_full_domain: "{{ service_subdomain }}.{{ service_domain }}" ``` ### Step 2: Replace with Direct Domain ```yaml # New pattern service_domain: "service.jnss.me" ``` ### Step 3: Update Template References ```jinja # Old {{ service_full_domain }} # New {{ service_domain }} ``` ### Step 4: Remove Unused Variables Delete `service_subdomain` and `service_full_domain` from defaults. ### Step 5: Add Explicit Host Configuration ```yaml # host_vars/arch-vps/main.yml service_domain: "service.jnss.me" ``` --- ## Testing Domain Configuration ### Verify Caddy Configuration ```bash # Check generated Caddy config cat /etc/caddy/sites-enabled/service.caddy # Test Caddy configuration syntax caddy validate --config /etc/caddy/Caddyfile # Check TLS certificate curl -I https://service.jnss.me ``` ### Verify Application Configuration ```bash # Check service configuration cat /etc/service/config.ini | grep -i domain # Test service accessibility curl https://service.jnss.me ``` ### Verify DNS Resolution ```bash # Check DNS resolution dig service.jnss.me # Test connectivity nc -zv service.jnss.me 443 ``` --- ## Checklist for New Services When creating a new service role: - [ ] Use direct domain specification (not subdomain composition) - [ ] Define domain(s) in `roles/service/defaults/main.yml` - [ ] Add explicit domain(s) to host_vars - [ ] Update all templates to use domain variable(s) - [ ] Document domain configuration in role README - [ ] Follow naming convention: `service_domain` or `service_[type]_domain` - [ ] Test with different domain configurations --- ## Summary **Standard Pattern:** ```yaml # Defaults: Provide reasonable default service_domain: "service.jnss.me" # Host vars: Always explicit in production service_domain: "service.jnss.me" # Templates: Use variable directly {{ service_domain }} ``` **Key Principles:** 1. Direct and explicit 2. One variable per domain 3. No forced inheritance 4. Consistent across all services 5. Flexible for any domain pattern --- **Rick-Infra Domain Configuration Standard** Simple, flexible, and consistent domain configuration for all services.