[{"data":1,"prerenderedAt":551},["ShallowReactive",2],{"navigation_docs":3,"-docs-deploy-domains":130,"-docs-deploy-domains-surround":546},[4,25,70,90,115],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting started",false,"\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","docs\u002F1.getting-started\u002F2.installation","i-lucide-terminal",{"title":21,"path":22,"stem":23,"icon":24},"Quickstart","\u002Fdocs\u002Fgetting-started\u002Fquickstart","docs\u002F1.getting-started\u002F3.quickstart","i-lucide-rocket",{"title":26,"icon":6,"path":27,"stem":28,"children":29,"page":6},"Deploy","\u002Fdocs\u002Fdeploy","docs\u002F2.deploy",[30,35,40,45,50,55,60,65],{"title":31,"path":32,"stem":33,"icon":34},"Projects and services","\u002Fdocs\u002Fdeploy\u002Fprojects-and-services","docs\u002F2.deploy\u002F1.projects-and-services","i-lucide-folder-kanban",{"title":36,"path":37,"stem":38,"icon":39},"Docker images","\u002Fdocs\u002Fdeploy\u002Fdocker-images","docs\u002F2.deploy\u002F2.docker-images","i-lucide-container",{"title":41,"path":42,"stem":43,"icon":44},"Git repositories","\u002Fdocs\u002Fdeploy\u002Fgit-repositories","docs\u002F2.deploy\u002F3.git-repositories","i-lucide-git-branch",{"title":46,"path":47,"stem":48,"icon":49},"Databases","\u002Fdocs\u002Fdeploy\u002Fdatabases","docs\u002F2.deploy\u002F4.databases","i-lucide-database",{"title":51,"path":52,"stem":53,"icon":54},"Environment variables","\u002Fdocs\u002Fdeploy\u002Fenvironment-variables","docs\u002F2.deploy\u002F5.environment-variables","i-lucide-key-round",{"title":56,"path":57,"stem":58,"icon":59},"Deployments and logs","\u002Fdocs\u002Fdeploy\u002Fdeployments","docs\u002F2.deploy\u002F6.deployments","i-lucide-scroll-text",{"title":61,"path":62,"stem":63,"icon":64},"Deploy hooks","\u002Fdocs\u002Fdeploy\u002Fdeploy-hooks","docs\u002F2.deploy\u002F7.deploy-hooks","i-lucide-webhook",{"title":66,"path":67,"stem":68,"icon":69},"Domains and HTTPS","\u002Fdocs\u002Fdeploy\u002Fdomains","docs\u002F2.deploy\u002F8.domains","i-lucide-lock",{"title":71,"icon":6,"path":72,"stem":73,"children":74,"page":6},"Backups","\u002Fdocs\u002Fbackups","docs\u002F3.backups",[75,80,85],{"title":76,"path":77,"stem":78,"icon":79},"Backup destinations","\u002Fdocs\u002Fbackups\u002Fbackup-destinations","docs\u002F3.backups\u002F1.backup-destinations","i-lucide-hard-drive-upload",{"title":81,"path":82,"stem":83,"icon":84},"Database backups","\u002Fdocs\u002Fbackups\u002Fdatabase-backups","docs\u002F3.backups\u002F2.database-backups","i-lucide-archive-restore",{"title":86,"path":87,"stem":88,"icon":89},"Backing up Harblet","\u002Fdocs\u002Fbackups\u002Fharblet-backups","docs\u002F3.backups\u002F3.harblet-backups","i-lucide-shield-check",{"title":91,"icon":6,"path":92,"stem":93,"children":94,"page":6},"Administration","\u002Fdocs\u002Fadministration","docs\u002F4.administration",[95,100,105,110],{"title":96,"path":97,"stem":98,"icon":99},"Harblet's domain","\u002Fdocs\u002Fadministration\u002Fharblet-domain","docs\u002F4.administration\u002F1.harblet-domain","i-lucide-globe",{"title":101,"path":102,"stem":103,"icon":104},"Servers","\u002Fdocs\u002Fadministration\u002Fservers","docs\u002F4.administration\u002F2.servers","i-lucide-server",{"title":106,"path":107,"stem":108,"icon":109},"Team and account","\u002Fdocs\u002Fadministration\u002Fteam","docs\u002F4.administration\u002F3.team","i-lucide-users",{"title":111,"path":112,"stem":113,"icon":114},"Updates","\u002Fdocs\u002Fadministration\u002Fupdates","docs\u002F4.administration\u002F4.updates","i-lucide-refresh-cw",{"title":116,"icon":6,"path":117,"stem":118,"children":119,"page":6},"Reference","\u002Fdocs\u002Freference","docs\u002F5.reference",[120,125],{"title":121,"path":122,"stem":123,"icon":124},"Troubleshooting","\u002Fdocs\u002Freference\u002Ftroubleshooting","docs\u002F5.reference\u002F1.troubleshooting","i-lucide-life-buoy",{"title":126,"path":127,"stem":128,"icon":129},"License","\u002Fdocs\u002Freference\u002Flicense","docs\u002F5.reference\u002F2.license","i-lucide-scale",{"id":131,"title":66,"body":132,"description":539,"extension":540,"links":541,"meta":542,"navigation":543,"path":67,"seo":544,"stem":68,"__hash__":545},"docs\u002Fdocs\u002F2.deploy\u002F8.domains.md",{"type":133,"value":134,"toc":523},"minimark",[135,144,149,210,213,253,256,259,268,272,275,330,334,345,371,374,378,381,394,402,406,409,412],[136,137,138,139,143],"p",{},"Visitors reach a service through its domains, always over HTTPS. Each domain needs a certificate that covers it, which an admin uploads once under ",[140,141,142],"strong",{},"SSL Certificates",".",[145,146,148],"h2",{"id":147},"add-a-domain","Add a domain",[150,151,153,158,169,180,184,192,196],"steps",{"level":152},"3",[154,155,157],"h3",{"id":156},"point-the-domain-at-the-first-server","Point the domain at the first server",[136,159,160,161,164,165,168],{},"Create a DNS ",[140,162,163],{},"A record"," for the domain with the IP address of your ",[140,166,167],{},"first server",", the one you installed Harblet on. All web traffic enters there, also for services that run on other servers.",[170,171,177],"pre",{"className":172,"code":174,"language":175,"meta":176},[173],"language-text","app.example.com.    A    203.0.113.10\n","text","",[178,179,174],"code",{"__ignoreMap":176},[154,181,183],{"id":182},"upload-a-certificate","Upload a certificate",[136,185,186,187,143],{},"If no certificate covers the domain yet, an admin uploads one. See ",[188,189,191],"a",{"href":190},"#certificates","Certificates",[154,193,195],{"id":194},"add-the-domain-to-the-service","Add the domain to the service",[136,197,198,199,202,203,206,207,143],{},"Open the service, go to ",[140,200,201],{},"Domains",", enter the domain, for example ",[178,204,205],{},"app.example.com",", and click ",[140,208,209],{},"Add domain",[136,211,212],{},"The domain works right away, without a deployment. Harblet sends its traffic to the service's port. Requests over plain HTTP are redirected to HTTPS.",[214,215,216,227,233,243],"ul",{},[217,218,219,222,223,226],"li",{},[140,220,221],{},"The service needs a port."," A service without one can't have domains. Set it under ",[140,224,225],{},"Settings"," and deploy. To remove the port later, remove the service's domains first.",[217,228,229,232],{},[140,230,231],{},"A domain belongs to one service."," It can't be used by two services, or by a service and Harblet itself.",[217,234,235,238,239,242],{},[140,236,237],{},"Wildcard domains"," such as ",[178,240,241],{},"*.example.com"," can't be added to a service. Add each subdomain instead. One wildcard certificate covers them all.",[217,244,245,246,249,250,143],{},"A service can have several domains, for example ",[178,247,248],{},"example.com"," and ",[178,251,252],{},"www.example.com",[136,254,255],{},"To remove a domain, click its trash button and confirm. It stops pointing at the service right away.",[145,257,191],{"id":258},"certificates",[136,260,261,262,143],{},"Harblet serves your own certificates. It doesn't request certificates from Let's Encrypt at the moment. Use a certificate from your provider or your company's CA, or get one from Let's Encrypt yourself, for example with ",[188,263,267],{"href":264,"rel":265},"https:\u002F\u002Fcertbot.eff.org",[266],"nofollow","Certbot",[269,270,271],"note",{},"Uploading and deleting certificates is for admins. Members who add a domain without a certificate are asked to have an admin upload one.",[154,273,183],{"id":274},"upload-a-certificate-1",[150,276,278,283,292,296,299,305,311,315,321,325],{"level":277},"4",[279,280,282],"h4",{"id":281},"open-ssl-certificates","Open SSL Certificates",[136,284,285,286,288,289,143],{},"Click ",[140,287,142],{}," in the sidebar, then ",[140,290,291],{},"Upload certificate",[279,293,295],{"id":294},"paste-the-certificate","Paste the certificate",[136,297,298],{},"Paste the certificate in PEM format, followed by its intermediate certificates:",[170,300,303],{"className":301,"code":302,"language":175,"meta":176},[173],"-----BEGIN CERTIFICATE-----\n(your certificate)\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n(intermediate certificate)\n-----END CERTIFICATE-----\n",[178,304,302],{"__ignoreMap":176},[136,306,307,308,143],{},"With Certbot, that's the content of ",[178,309,310],{},"fullchain.pem",[279,312,314],{"id":313},"paste-the-private-key","Paste the private key",[136,316,317,318,143],{},"Paste the private key in PEM format, without a passphrase. With Certbot, that's ",[178,319,320],{},"privkey.pem",[279,322,324],{"id":323},"upload-it","Upload it",[136,326,285,327,329],{},[140,328,291],{},". Harblet checks that the key belongs to the certificate and that the certificate is valid, then uses it right away for the domains it covers, following the rules below.",[154,331,333],{"id":332},"which-domains-a-certificate-covers","Which domains a certificate covers",[136,335,336,337,340,341,344],{},"The ",[140,338,339],{},"Covers"," column lists the domain names in the certificate, and ",[140,342,343],{},"Used by"," shows how many domains use it.",[214,346,347,353],{},[217,348,349,350,352],{},"A name like ",[178,351,205],{}," covers exactly that domain.",[217,354,355,356,358,359,249,361,364,365,367,368,143],{},"A wildcard like ",[178,357,241],{}," covers one level of subdomains: ",[178,360,205],{},[178,362,363],{},"api.example.com",", but not ",[178,366,248],{}," itself and not ",[178,369,370],{},"a.b.example.com",[136,372,373],{},"When several certificates cover a domain, Harblet uses one with the exact name over a wildcard, and otherwise the one that expires last. Expired certificates never count.",[154,375,377],{"id":376},"renew-a-certificate","Renew a certificate",[136,379,380],{},"Upload the renewed certificate before the old one expires. Harblet switches every domain it covers to the new certificate right away. Then delete the old one.",[136,382,336,383,386,387,390,391,143],{},[140,384,385],{},"Expires"," column marks certificates that expire within 30 days with ",[140,388,389],{},"Expires soon",", and past ones with ",[140,392,393],{},"Expired",[395,396,397,398,401],"warning",{},"A domain whose only certificate expired shows ",[140,399,400],{},"No certificate",". Upload a new certificate for it as soon as possible.",[154,403,405],{"id":404},"delete-a-certificate","Delete a certificate",[136,407,408],{},"Click the trash button of a certificate and confirm. Harblet refuses if a domain would be left without a valid certificate, including Harblet's own domain. Upload the replacement or remove the domain first.",[145,410,121],{"id":411},"troubleshooting",[413,414,415,428],"table",{},[416,417,418],"thead",{},[419,420,421,425],"tr",{},[422,423,424],"th",{},"Problem",[422,426,427],{},"What to check",[429,430,431,443,451,459,467,475,488,499,507,515],"tbody",{},[419,432,433,437],{},[434,435,436],"td",{},"\"This service has no port\"",[434,438,439,440,442],{},"Set the service's port under ",[140,441,225],{}," and deploy.",[419,444,445,448],{},[434,446,447],{},"\"Upload a certificate for this domain under SSL Certificates first.\", or for members \"Ask an admin to upload a certificate for this domain first.\"",[434,449,450],{},"No valid certificate covers the domain. Upload one, or check that a wildcard covers this level of subdomain.",[419,452,453,456],{},[434,454,455],{},"\"This domain is already used by a service.\"",[434,457,458],{},"Remove the domain from the other service first.",[419,460,461,464],{},[434,462,463],{},"\"This domain is used by Harblet itself.\"",[434,465,466],{},"Harblet's own domain can't be added to a service. Use another subdomain.",[419,468,469,472],{},[434,470,471],{},"\"The certificate has no DNS names\"",[434,473,474],{},"Harblet reads the domains from the certificate's subject alternative names. Use a certificate that lists the domain there, not only as its common name.",[419,476,477,480],{},[434,478,479],{},"\"This private key does not belong to the certificate\"",[434,481,482,483,485,486,143],{},"Paste the key that belongs to this certificate. With Certbot, that's ",[178,484,320],{}," next to ",[178,487,310],{},[419,489,490,493],{},[434,491,492],{},"\"Remove the passphrase from the private key\"",[434,494,495,496,143],{},"Export the key without a passphrase, for example with ",[178,497,498],{},"openssl pkey -in key.pem -out key-plain.pem",[419,500,501,504],{},[434,502,503],{},"\"The certificate has expired\" or \"The certificate is not valid yet\"",[434,505,506],{},"Check the certificate's dates and upload a current one.",[419,508,509,512],{},[434,510,511],{},"The browser can't reach the domain",[434,513,514],{},"Check that the A record points at the first server and that ports 80 and 443 are open in its firewall.",[419,516,517,520],{},[434,518,519],{},"The browser shows the wrong certificate",[434,521,522],{},"Make sure the uploaded certificate covers the domain and hasn't expired. If an expired certificate is still listed, delete it.",{"title":176,"searchDepth":524,"depth":524,"links":525},2,[526,532,538],{"id":147,"depth":524,"text":148,"children":527},[528,530,531],{"id":156,"depth":529,"text":157},3,{"id":182,"depth":529,"text":183},{"id":194,"depth":529,"text":195},{"id":258,"depth":524,"text":191,"children":533},[534,535,536,537],{"id":274,"depth":529,"text":183},{"id":332,"depth":529,"text":333},{"id":376,"depth":529,"text":377},{"id":404,"depth":529,"text":405},{"id":411,"depth":524,"text":121},"Point your domains at a service and secure them with your own certificates.","md",null,{},{"icon":69},{"title":66,"description":539},"IljYOXt15FFifwxgNok93avXXoGli40YtHSlQ01gqk8",[547,549],{"title":61,"path":62,"stem":63,"description":548,"icon":64,"children":-1},"Deploy a service from your CI pipeline with one POST request.",{"title":76,"path":77,"stem":78,"description":550,"icon":79,"children":-1},"Add an Amazon S3 or S3-compatible bucket that databases and Harblet back up to.",1794744117208]