Files
cloudron-box/src/views/domains.html

349 lines
21 KiB
HTML
Raw Normal View History

<!-- Modal subscription -->
<div class="modal fade" id="subscriptionRequiredModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
2020-06-23 17:21:22 -07:00
<h4 class="modal-title">Subscription required</h4>
</div>
<div class="modal-body">
2020-06-23 17:21:22 -07:00
<p>To add more domains, please setup a paid plan.</p>
</div>
<div class="modal-footer">
2020-06-23 17:21:22 -07:00
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-success" ng-click="openSubscriptionSetup()">Setup Subscription</button>
</div>
</div>
</div>
</div>
2019-02-06 15:53:01 -08:00
<!-- modal domain add/configure -->
2018-01-22 13:01:38 -08:00
<div class="modal fade" id="domainConfigureModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" ng-show="domainConfigure.adding">Add Domain</h4>
<h4 class="modal-title" ng-hide="domainConfigure.adding">Configure {{ domainConfigure.domain.domain }}</h4>
</div>
<div class="modal-body">
2020-09-01 21:33:20 -07:00
<p ng-show="domainConfigure.adding">Adding a domain lets you install apps on subdomains of this domain. Email settings for the domain can be configured in the Email view.</p>
2018-01-22 13:01:38 -08:00
<form name="domainConfigureForm" role="form" novalidate ng-submit="domainConfigure.submit()" autocomplete="off">
<fieldset>
<p class="has-error text-center" ng-show="domainConfigure.error">{{ domainConfigure.error }}</p>
<div class="form-group" ng-show="domainConfigure.adding">
2018-01-22 13:01:38 -08:00
<label class="control-label">Domain name</label>
<input type="text" class="form-control" ng-model="domainConfigure.newDomain" name="newDomain" ng-disabled="domainConfigure.busy" placeholder="example.com" ng-required="domainConfigure.adding" autofocus>
</div>
<div class="form-group">
2020-09-09 10:08:13 -07:00
<label class="control-label">DNS Provider <sup><a ng-href="https://docs.cloudron.io/domains/#dns-providers" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
<select class="form-control" ng-model="domainConfigure.provider" ng-options="a.value as a.name for a in dnsProvider" ng-change="domainConfigure.setDefaultTlsProvider()"></select>
2018-01-22 13:01:38 -08:00
</div>
<!-- Route53 -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'route53'">
2018-06-04 21:06:44 -07:00
<label class="control-label">Access Key Id</label>
2018-01-22 13:01:38 -08:00
<input type="text" class="form-control" ng-model="domainConfigure.accessKeyId" name="accessKeyId" ng-disabled="domainConfigure.busy" ng-minlength="16" ng-maxlength="32" ng-required="domainConfigure.provider === 'route53'">
</div>
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'route53'">
2018-06-04 21:06:44 -07:00
<label class="control-label">Secret Access Key</label>
2018-01-22 13:01:38 -08:00
<input type="text" class="form-control" ng-model="domainConfigure.secretAccessKey" name="secretAccessKey" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'route53'">
</div>
<!-- Google Cloud DNS -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'gcdns'">
2018-06-04 21:06:44 -07:00
<label class="control-label">Service Account Key</label>
2018-01-22 13:01:38 -08:00
<div class="input-group">
<input type="file" id="gcdnsKeyFileInput" style="display:none"/>
<input type="text" class="form-control" placeholder="Service Account Key" ng-model="domainConfigure.gcdnsKey.keyFileName" id="gcdnsKeyInput" name="cert" onclick="getElementById('gcdnsKeyFileInput').click();" style="cursor: pointer;" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'gcdns'">
<span class="input-group-addon">
<i class="fa fa-upload" onclick="getElementById('gcdnsKeyFileInput').click();"></i>
</span>
</div>
</div>
<!-- DigitalOcean -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'digitalocean'">
2018-06-04 21:06:44 -07:00
<label class="control-label">DigitalOcean Token</label>
2018-01-22 13:01:38 -08:00
<input type="text" class="form-control" ng-model="domainConfigure.digitalOceanToken" name="digitalOceanToken" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'digitalocean'">
</div>
<!-- Gandi -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'gandi'">
<label class="control-label">Gandi API Key</label>
<input type="text" class="form-control" ng-model="domainConfigure.gandiApiKey" name="gandiApiKey" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'gandi'">
</div>
2018-05-06 21:52:25 -07:00
<!-- GoDaddy -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'godaddy'">
2019-02-06 15:53:01 -08:00
<label class="control-label">API Key</label>
2018-05-06 21:52:25 -07:00
<input type="text" class="form-control" ng-model="domainConfigure.godaddyApiKey" name="apiKey" ng-disabled="domainConfigure.busy" ng-minlength="1" ng-required="domainConfigure.provider === 'godaddy'">
</div>
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'godaddy'">
<label class="control-label">API Secret</label>
<input type="text" class="form-control" ng-model="domainConfigure.godaddyApiSecret" name="apiSecret" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'godaddy'">
</div>
2018-01-22 13:01:38 -08:00
<!-- Cloudflare -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'cloudflare'">
2020-01-01 16:02:50 -08:00
<label class="control-label">Token Type</label>
<select class="form-control" ng-model="domainConfigure.cloudflareTokenType">
<option value="GlobalApiKey">Global API Key</option>
<option value="ApiToken">API Token</option>
</select>
2018-01-22 13:01:38 -08:00
</div>
2020-01-01 16:02:50 -08:00
2018-01-22 13:01:38 -08:00
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'cloudflare'">
2020-01-01 16:02:50 -08:00
<label class="control-label" ng-show="domainConfigure.cloudflareTokenType === 'GlobalApiKey'">Global API Key</label>
<label class="control-label" ng-show="domainConfigure.cloudflareTokenType === 'ApiToken'">Api Token</label>
<input type="text" class="form-control" ng-model="domainConfigure.cloudflareToken" name="cloudflareToken" placeholder="API Key/Token" ng-required="domainConfigure.provider === 'cloudflare'" ng-disabled="domainConfigure.busy">
</div>
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'cloudflare' && domainConfigure.cloudflareTokenType === 'GlobalApiKey'">
2018-06-04 21:06:44 -07:00
<label class="control-label">Cloudflare Email</label>
2020-01-01 16:02:50 -08:00
<input type="email" class="form-control" ng-model="domainConfigure.cloudflareEmail" name="cloudflareEmail" placeholder="Cloudflare Account Email" ng-required="domainConfigure.provider === 'cloudflare' && domainConfigure.cloudflareTokenType === 'GlobalApiKey'" ng-disabled="domainConfigure.busy">
2018-01-22 13:01:38 -08:00
</div>
2020-03-12 17:13:21 -07:00
<!-- Linode -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'linode'">
<label class="control-label">Linode Token</label>
<input type="text" class="form-control" ng-model="domainConfigure.linodeToken" name="linodeToken" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'linode'">
</div>
2018-05-09 12:24:46 +02:00
<!-- Name.com -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'namecom'">
2018-06-04 21:06:44 -07:00
<label class="control-label">Name.com Username</label>
2018-05-09 12:24:46 +02:00
<input type="text" class="form-control" ng-model="domainConfigure.nameComUsername" name="nameComUsername" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'namecom'">
</div>
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'namecom'">
2019-02-06 15:53:01 -08:00
<label class="control-label">API Token</label>
2018-05-09 12:24:46 +02:00
<input type="text" class="form-control" ng-model="domainConfigure.nameComToken" name="nameComToken" ng-disabled="domainConfigure.busy" ng-minlength="1" ng-required="domainConfigure.provider === 'namecom'">
</div>
2019-01-22 11:26:24 +01:00
<!-- Namecheap -->
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'namecheap'">
<label class="control-label">Namecheap Username</label>
<input type="text" class="form-control" ng-model="domainConfigure.namecheapUsername" name="namecheapUsername" ng-disabled="domainConfigure.busy" ng-required="domainConfigure.provider === 'namecheap'">
</div>
<div class="form-group" ng-class="{ 'has-error': false }" ng-show="domainConfigure.provider === 'namecheap'">
2019-02-06 15:53:01 -08:00
<label class="control-label">API Key</label>
2020-03-12 17:13:21 -07:00
<p class="small text-info">
<b>The server IP needs to be whitelisted for this API Key.</b>
</p>
2019-01-22 11:26:24 +01:00
<input type="text" class="form-control" ng-model="domainConfigure.namecheapApiKey" name="namecheapApiKey" ng-disabled="domainConfigure.busy" ng-minlength="1" ng-required="domainConfigure.provider === 'namecheap'">
</div>
2020-03-12 17:13:21 -07:00
<p class="small text-warning" ng-show="domainConfigure.provider === 'linode'">
2020-09-09 10:08:13 -07:00
<b>Linode DNS average <a target="_blank" ng-href="https://docs.cloudron.io/domains/#linode-dns">propagation time</a> is 30 minutes. Installing apps &amp; and getting a Let's Encrypt certificate will take a while.</b>
2020-03-12 17:13:21 -07:00
</p>
2018-09-12 11:45:07 -07:00
<p class="small text-info" ng-show="domainConfigure.provider === 'wildcard'">
2018-01-22 13:01:38 -08:00
Setup <i>A</i> records for <b>*.{{ domainConfigure.newDomain || domainConfigure.domain.domain }}</b> and <b>{{ domainConfigure.newDomain || domainConfigure.domain.domain }}</b> to this server's IP.
</p>
2018-09-12 11:45:07 -07:00
<p class="small text-info" ng-show="domainConfigure.provider === 'manual'">
2018-03-12 15:04:37 -07:00
<b>All DNS records have to be setup manually before each app installation.</b>
2018-01-22 13:01:38 -08:00
</p>
<p class="small text-info" ng-show="needsPort80(domainConfigure.provider, domainConfigure.tlsConfig.provider)">Let's Encrypt requires your server to be reachable on port 80</p>
<a href="" ng-click="domainConfigure.advancedVisible = true" ng-hide="domainConfigure.advancedVisible">Advanced settings...</a>
<div uib-collapse="!domainConfigure.advancedVisible">
<div class="form-group">
2020-09-09 10:08:13 -07:00
<label class="control-label">Zone Name (Optional) <sup><a ng-href="https://docs.cloudron.io/domains/#zone-name" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
2018-08-27 13:50:13 -07:00
<input type="text" class="form-control" ng-model="domainConfigure.zoneName" name="zoneName" ng-disabled="domainConfigure.busy">
</div>
<div class="form-group">
2020-09-09 10:08:13 -07:00
<label class="control-label">Certificate Provider <sup><a ng-href="https://docs.cloudron.io/certificates/#certificate-providers" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
<select class="form-control" ng-model="domainConfigure.tlsConfig.provider" ng-options="a.value as a.name for a in tlsProvider"></select>
</div>
2018-08-27 12:03:01 -07:00
<!-- Fallback certificate -->
<div ng-show="domainConfigure.tlsConfig.provider !== 'fallback'">
<label class="control-label">Fallback Certificate (optional)</label>
<p>
Certificates are automatically obtained and renewed from <a href="https://letsencrypt.org/" target="_blank">Lets Encrypt</a>. See the current rate limit <a href="https://letsencrypt.org/docs/rate-limits/" target="_blank">here</a>.
This wildcard certificate will be used should getting a Lets Encrypt certificate fail. If not provided, an automatically generated self-signed certificate will be used as fallback.
</p>
</div>
<div ng-show="domainConfigure.tlsConfig.provider === 'fallback'">
<label class="control-label">Custom Certificate</label>
<p>
2020-09-09 10:08:13 -07:00
This <a ng-href="https://docs.cloudron.io/certificates/#custom-certificates" target="_blank">wildcard certificate</a> will be used for all apps on this domain. If not provided, a self-signed certificate will be automatically generated.
</p>
</div>
<div class="form-group" ng-class="{ 'has-error': (!fallbackCert.cert.$dirty && fallbackCert.error) }">
<div class="input-group">
<input type="file" id="fallbackCertFileInput" style="display:none"/>
<input type="text" class="form-control" placeholder="Certificate" ng-model="domainConfigure.fallbackCert.certificateFileName" name="cert" onclick="getElementById('fallbackCertFileInput').click();" style="cursor: pointer;" ng-disabled="domainConfigure.busy">
<span class="input-group-addon">
<i class="fa fa-upload" onclick="getElementById('fallbackCertFileInput').click();"></i>
</span>
</div>
</div>
<div class="form-group" ng-class="{ 'has-error': (!fallbackCert.key.$dirty && fallbackCert.error) }">
<div class="input-group">
<input type="file" id="fallbackKeyFileInput" style="display:none"/>
<input type="text" class="form-control" placeholder="Key" ng-model="domainConfigure.fallbackCert.keyFileName" id="fallbackKeyInput" name="key" onclick="getElementById('fallbackKeyFileInput').click();" style="cursor: pointer;" ng-disabled="domainConfigure.busy">
<span class="input-group-addon">
<i class="fa fa-upload" onclick="getElementById('fallbackKeyFileInput').click();"></i>
</span>
</div>
</div>
2018-08-27 13:50:13 -07:00
</div> <!-- advanced -->
2018-01-22 13:01:38 -08:00
<input class="ng-hide" type="submit" ng-disabled="domainConfigureForm.$invalid || domainConfigure.busy"/>
</fieldset>
</form>
</div>
<div class="modal-footer ">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="domainConfigure.submit()" ng-disabled="domainConfigureForm.$invalid || domainConfigure.busy">
<i class="fa fa-circle-notch fa-spin" ng-show="domainConfigure.busy"></i> Save
2018-01-22 13:01:38 -08:00
</button>
</div>
</div>
</div>
</div>
<!-- Modal domain remove -->
<div class="modal fade" id="domainRemoveModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Really remove {{ domainRemove.domain.domain }} ?</h4>
</div>
<div class="modal-body">
This will delete the domain <code>{{ domainRemove.domain.domain }}</code>.
<div>
<br/>
<span class="has-error" ng-show="domainRemove.error">{{ domainRemove.error }}</span>
</div>
2018-01-22 13:01:38 -08:00
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger" ng-click="domainRemove.submit()" ng-disabled="domainRemove.busy"><i class="fa fa-circle-notch fa-spin" ng-show="domainRemove.busy"></i> Remove</button>
2018-01-22 13:01:38 -08:00
</div>
</div>
</div>
</div>
<div class="content">
<div class="text-left">
<h1>{{ 'domains.title' | tr }} <button class="btn btn-primary btn-outline pull-right" ng-click="domainAdd.show()"><i class="fa fa-plus"></i> Add Domain</button></h1>
2018-01-22 13:01:38 -08:00
</div>
<div class="card card-large">
<div class="row ng-hide" ng-show="!ready">
<div class="col-lg-12 text-center">
<h2><i class="fa fa-circle-notch fa-spin"></i></h2>
2018-01-22 13:01:38 -08:00
</div>
</div>
<div class="row animateMeOpacity ng-hide" ng-show="ready">
<div class="col-lg-12">
<table class="table table-hover" style="margin-top: 10px;">
<thead>
<tr>
<th>Domain</th>
<th class="text-left hidden-xs hidden-sm">Provider</th>
<th style="width: 100px" class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="domain in domains">
2020-02-13 21:15:09 -08:00
<td class="elide-table-cell hand" ng-click="domain.provider !== 'caas' && domainConfigure.show(domain)">
{{ domain.domain }}
</td>
2020-02-13 21:15:09 -08:00
<td class="text-left elide-table-cell hidden-xs hidden-sm hand" ng-click="domain.provider !== 'caas' && domainConfigure.show(domain)">
{{ prettyProviderName(domain) }}
</td>
<td class="text-right no-wrap" style="vertical-align: bottom">
2020-02-13 21:15:09 -08:00
<button class="btn btn-xs btn-default" ng-click="domainConfigure.show(domain)" ng-show="domain.provider !== 'caas'" title="Edit Domain"><i class="fa fa-pencil-alt"></i></button>
<button class="btn btn-xs btn-danger" ng-click="domainRemove.show(domain)" ng-show="domain.provider !== 'caas'" title="Remove Domain" ng-disabled="domain.domain === config.adminDomain"><i class="far fa-trash-alt"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
2018-12-11 09:57:46 -08:00
</div>
2018-12-13 15:53:53 -08:00
<div class="text-left">
2018-12-11 09:57:46 -08:00
<h3>Renew certificates</h3>
</div>
<div class="card">
<div class="row">
<div class="col-md-12">
<p>
2018-12-13 13:58:08 +01:00
Cloudron renews Let's Encrypt certificates automatically. Use this option to trigger a renewal immediately.
2018-12-11 09:57:46 -08:00
</p>
2018-01-22 13:01:38 -08:00
</div>
</div>
<div class="row">
<div class="col-md-12" style="margin-bottom: 10px;">
<div ng-show="renewCerts.busy" class="progress progress-striped active animateMe">
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ renewCerts.percent }}%"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<p ng-show="renewCerts.busy">{{ renewCerts.message }}</p>
<p ng-hide="renewCerts.busy">
<div class="has-error" ng-show="!renewCerts.active">{{ renewCerts.errorMessage }}</div>
</p>
</div>
<div class="col-md-6 text-right">
<button class="btn btn-outline btn-primary" ng-click="renewCerts.renew()" ng-disabled="renewCerts.busy" style="margin-right: 10px">Renew All Certs</button>
<a class="btn btn-primary pull-right" ng-href="/logs.html?taskId={{renewCerts.taskId}}" ng-disabled="!renewCerts.taskId" target="_blank">Show Logs</a>
</div>
</div>
2018-12-18 15:05:11 -08:00
</div>
2020-02-04 12:55:51 -08:00
<div class="text-left">
2018-12-18 15:05:11 -08:00
<h3>Change Dashboard Domain</h3>
</div>
2020-02-04 12:55:51 -08:00
<div class="card">
2018-12-18 15:05:11 -08:00
<div class="row">
<div class="col-md-8">
<p>
2020-08-10 13:11:10 -07:00
This will move the dashboard and the email server to the <code>my</code>subdomain of the selected domain.
2018-12-18 15:05:11 -08:00
</p>
</div>
<div class="col-md-4">
<select class="form-control pull-right" style="display: inline-block; width: 200px;" ng-model="changeDashboard.selectedDomain" ng-options="a.domain for a in domains"></select>
</div>
</div>
<div class="row">
<div class="col-md-12" style="margin-bottom: 10px;">
<div ng-show="changeDashboard.busy" class="progress progress-striped active animateMe">
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ changeDashboard.percent }}%"></div>
</div>
</div>
</div>
2018-12-18 15:05:11 -08:00
<div class="row">
<div class="col-md-6">
<p ng-show="changeDashboard.busy">{{ changeDashboard.message }}</p>
<p ng-hide="changeDashboard.busy">
<div class="has-error" ng-show="!changeDashboard.active">{{ changeDashboard.errorMessage }}</div>
</p>
</div>
<div class="col-md-6 text-right">
2019-01-06 16:25:25 -08:00
<button class="btn btn-outline btn-primary" ng-click="changeDashboard.change()" ng-hide="changeDashboard.busy" ng-disabled="changeDashboard.selectedDomain.domain === changeDashboard.adminDomain.domain">Change Domain</button>
2019-01-06 14:52:36 -08:00
<button class="btn btn-outline btn-danger" ng-click="changeDashboard.stop()" ng-show="changeDashboard.busy" style="margin-right: 10px">Cancel</button>
<a class="btn btn-primary pull-right" ng-href="/logs.html?taskId={{changeDashboard.taskId}}" ng-show="changeDashboard.busy" target="_blank">Show Logs</a>
2018-12-18 15:05:11 -08:00
</div>
</div>
2018-01-22 13:01:38 -08:00
</div>
</div>