Last reviewed: 2026-10-05
DNS records and custom domains
Table of contents
- Which DNS domains (zones) can I use?
- How to control DNS
- DNS records not belonging to a specific deployment
Which DNS domains (zones) can I use?
Each cluster is connected to an AWS account which has got one or more associated dns zones or domains.
Each namespace you control via your team’s apps-repository can modify DNS records within any zone in that cluster’s account.
Each account only allows binding to a limited set of domains. The available domains for your namespace are listed in the README file in the apps repository, under your namespace. For pol-dev, see: apps-pol/pol-dev/README.md
The list can be extended for your account. This requires some configuration on our side, so write to the IDP team in your team’s onboarding channel on Slack if you need an additional domain enabled.
Domains for an account may change. Please act responsibly while working with DNS: there may be zones logically belonging to other teams also hosted in the same cluster. Please don’t experiment with such zones.
How to control DNS
The most straightforward way to work with DNS is to use the idp-advanced chart, where you list the fully qualified domain names (FQDNs) you want for each service in the ingress.fqdn field of your values.yaml. When you use this field, DNS records are created automatically and a certificate is issued for the domain. DNS and certificate issuance are both handled for you.
Once a domain is available for your account, you can add subdomains under it in the ingress.fqdn field of each application’s values.yaml.
Using a domain hosted in another account or by another team
It’s also possible to point a domain that isn’t on your account’s list to your service, but it’s more involved:
- Contact the owner of the root domain and ask them to create an A record pointing to the load balancer addresses listed in your namespace’s README.
- Once that record is in place, add the address in the
ingress.fqdnfield of yourvalues.yamland setingress.public.httpCertChallenge: true. Certificate issuance will then happen automatically.
Private hostnames
If you enable the private ingress (ingress.private.enabled: true), each name in ingress.fqdn also gets a private hostname with internal- in front of it, which resolves to private IP addresses. To use other hostnames on the private ingress, list them in ingress.private.fqdn. They are then used as they are, without the prefix.
Example: private hostname with the default prefix
ingress:
enabled: true
fqdn:
- foo.bar.idp.jppol.dk
private:
enabled: true
| Ingress | Hostname |
|---|---|
| Public | foo.bar.idp.jppol.dk |
| Private | internal-foo.bar.idp.jppol.dk |
Example: your own private hostname
ingress:
enabled: true
fqdn:
- foo.bar.idp.jppol.dk
private:
enabled: true
fqdn:
- foo-private.bar.idp.jppol.dk
| Ingress | Hostname |
|---|---|
| Public | foo.bar.idp.jppol.dk |
| Private | foo-private.bar.idp.jppol.dk |
Example: private only, without the prefix
If the service should only be reachable privately, without the internal- prefix, turn off the public ingress and put the name in ingress.private.fqdn:
ingress:
enabled: true
public:
enabled: false
private:
enabled: true
fqdn:
- foo.bar.idp.jppol.dk
| Ingress | Hostname |
|---|---|
| Public | none |
| Private | foo.bar.idp.jppol.dk |
DNS records not belonging to a specific deployment
It is possible to set arbitrary records in a given dns zone without the records being related to web services or other deployments inside the cluster.
Here you can use the chart crossplane-route53-records.
This chart becomes relevant when you
- Want to create validation records of type
TXT - Want to prepare a migration by creating CNAMEs to deployments hosted outside IDP.
- Want to setup MX records
Where to put your records
Each namespace has a zones folder (apps/<namespace>/zones/) that the IDP platform creates and keeps up to date. It makes the zones in the account available to records in the namespace. Don’t edit it, and don’t put your own records there.
Put your records in a folder of their own in your namespace, for example apps/<namespace>/dns-records/. You can use one folder for all your records or one folder per “purpose”.
Add an application.yaml to the folder that references the chart helm/crossplane-route53-records:
apiVersion: v2
name: dns-records
description: DNS records for the zones available in the namespace
version: 0.1.0
helm:
chart: helm/crossplane-route53-records
chartVersion: "3.0.10"
Records in values.yaml
In the values.yaml file you can specify the needed records in the array records.
Each record should reference a zone using the attribute zoneName. Simply use the fully qualified domain name for any zone hosted in the cluster.
You must also provide a ttl (in seconds), the actual values in the records array and of course the record type in type.
The name field should contain the subdomain part of a CNAME or A record. To create an A record pointing foo.bar.idp.jppol.dk to the ip address 1.2.3.4 you should use a record like
records:
- zoneName: bar.idp.jppol.dk
name: foo
records:
- "1.2.3.4"
ttl: 120
type: A
To create a record for the zone itself (the apex), set name to an empty string. To create a wildcard record, set name to "*":
records:
- zoneName: bar.idp.jppol.dk
name: ""
records:
- "1.2.3.4"
ttl: 300
type: A
- zoneName: bar.idp.jppol.dk
name: "*"
records:
- "1.2.3.4"
ttl: 300
type: A
The supported record types are A, AAAA, CNAME, MX, TXT, SRV, NS, PTR and SOA.
Each combination of zoneName, name and type can only be used once in a namespace. To give a record more than one value, list all the values in its records array.
A full set of examples below.
records:
- zoneName: bar.idp.jppol.dk
name: _0123456789abcdef0123456789abcdef
records:
- _fedcba9876543210fedcba9876543210.abcdefghij.acm-validations.aws.
ttl: 60
type: CNAME
- zoneName: bar.idp.jppol.dk
name: _dmarc
records:
- "v=DMARC1; p=none;"
ttl: 300
type: TXT
- zoneName: bar.idp.jppol.dk
type: MX
name: mail
records:
- "10 feedback-smtp.eu-west-1.amazonses.com"
ttl: 300
- zoneName: bar.idp.jppol.dk
type: TXT
name: mail
records:
- "v=spf1 include:amazonses.com ~all"
ttl: 300
Crossplane policies for DNS records
The Route53 records chart exposes Crossplane policy controls in values:
managementPolicies: Control # Control = create/update; Observe = adopt existing records
deletionPolicy: Delete # Delete = allow deletions; Orphan = leave records behind
- Records
- Control => Crossplane creates and updates DNS records.
- Observe => Crossplane does not create or update records. This can be used to adopt records that already exist.
- If
deletionPolicyis Delete, Delete is also included so removing a record fromvalues.yamlwill delete it in Route53. With Orphan, removals in values do not delete existing records. - Delete is included with Observe as well. To adopt existing records without risking that they are deleted, set
deletionPolicy: Orphantogether withmanagementPolicies: Observe.
- Zones are always rendered with
managementPolicies: ["Observe"]and cannot be created by this chart; the IDP platform manages zones.
Conflicting records
If you set identical DNS records in both idp-advanced and the route53-chart, the system backing idp-advanced will compete with the system supporting route53. There is currently no detection of this.