1710 lines
		
	
	
	
		
			78 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			1710 lines
		
	
	
	
		
			78 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <div class="config-setup-tool-element">
 | |
|   <div class="cor-loader" ng-if="!config"></div>
 | |
|   <div ng-show="true">
 | |
|     <form id="configform" name="configform">
 | |
| 
 | |
|     <!-- Custom SSL certificates -->
 | |
|     <div class="co-panel" id="custom-ssl">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-certificate"></i> Custom SSL Certificates
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="config-certificates-field"></div>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- Basic Configuration -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fas fa-cogs"></i> Basic Configuration
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <table class="config-table">
 | |
|           <tr>
 | |
|             <td>Enterprise Logo URL:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.ENTERPRISE_LOGO_URL"
 | |
|                     placeholder="http://example.com/logo.png"></span>
 | |
|               <div class="help-text">
 | |
|                 Enter the full URL to your company's logo.
 | |
|               </div>
 | |
|             </td>
 | |
|             <td>
 | |
|               <img class="registry-logo-preview" ng-src="{{ config.ENTERPRISE_LOGO_URL }}">
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">Contact Information:</td>
 | |
|             <td colspan="2">
 | |
|               <span class="config-contacts-field" binding="config.CONTACT_INFO"></span>
 | |
|               <div class="help-text" style="margin-top: 10px;">
 | |
|                 Information to show in the Contact Page. If none specified, CoreOS contact information
 | |
|                 is displayed.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- Server Configuration -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-cloud"></i> Server Configuration
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <table class="config-table">
 | |
|           <tr>
 | |
|             <td>Server Hostname:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.SERVER_HOSTNAME"
 | |
|                     placeholder="Hostname (and optional port if non-standard)"
 | |
|                     pattern="{{ HOSTNAME_REGEX }}"></span>
 | |
|               <div class="help-text">
 | |
|                  The HTTP host (and optionally the port number if a non-standard HTTP/HTTPS port) of the location
 | |
|                   where the registry will be accessible on the network
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>TLS:</td>
 | |
|             <td>
 | |
|               <select class="form-control" ng-model="mapped.TLS_SETTING">
 | |
|                 <option value="internal-tls">Quay Enterprise handles TLS</option>
 | |
|                 <option value="external-tls">My own load balancer handles TLS (Not Recommended)</option>
 | |
|                 <option value="none">None (Not For Production)</option>
 | |
|               </select>
 | |
| 
 | |
|               <div class="co-alert co-alert-danger" ng-if="mapped.TLS_SETTING == 'none'" style="margin-bottom: 20px">
 | |
|                 Running without TLS should not be used for production workloads!
 | |
|               </div>
 | |
| 
 | |
|               <div class="co-alert co-alert-warning" ng-if="mapped.TLS_SETTING == 'external-tls'" style="margin-bottom: 20px">
 | |
|                 Terminating TLS outside of Quay Enterprise can result in unusual behavior if the external load balancer is not
 | |
|                 configured properly. <strong>This option is not recommended for simple setups</strong>. Please contact support
 | |
|                 if you encounter problems while using this option.
 | |
|               </div>
 | |
| 
 | |
|               <div class="co-alert co-alert-info" ng-if="mapped.TLS_SETTING == 'internal-tls'" style="margin-bottom: 20px">
 | |
|                 Enabling TLS also enables <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security">HTTP Strict Transport Security</a>.<br/>
 | |
|                 This prevents downgrade attacks and cookie theft, but browsers will reject all future insecure connections on this hostname.
 | |
|               </div>
 | |
| 
 | |
|               <table class="config-table"  ng-if="mapped.TLS_SETTING == 'internal-tls'">
 | |
|                 <tr>
 | |
|                   <td class="non-input">Certificate:</td>
 | |
|                   <td>
 | |
|                     <span class="config-file-field" filename="ssl.cert" has-file="hasfile.SSLCert"></span>
 | |
|                     <div class="help-text">
 | |
|                       The certificate must be in PEM format.
 | |
|                     </div>
 | |
|                   </td>
 | |
|                 </tr>
 | |
|                 <tr>
 | |
|                   <td class="non-input">Private key:</td>
 | |
|                   <td>
 | |
|                     <span class="config-file-field" filename="ssl.key" has-file="hasfile.SSLKey"></span>
 | |
|                   </td>
 | |
|                 </tr>
 | |
|               </table>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
| 
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- Consistency Settings -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa ci-shared-database"></i> Data Consistency Settings
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>Relax constraints on consistency guarantees for specific operations
 | |
|             to enable higher performance and availability.
 | |
|           </p>
 | |
|         </div>
 | |
|         <table class="config-table">
 | |
|           <tr>
 | |
|             <td>
 | |
|               <div class="config-bool-field" binding="config.ALLOW_PULLS_WITHOUT_STRICT_LOGGING">
 | |
|                 Allow repository pulls even if audit logging fails.
 | |
|                 <div class="help-text">
 | |
|                   If enabled, failures to write to the audit log will fallback from
 | |
|                   the database to the standard logger for registry pulls.
 | |
|                 </div>
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /Consistency Settings -->
 | |
| 
 | |
|     <!-- Time Machine -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-history"></i> Time Machine
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>Time machine keeps older copies of tags within a repository for the configured period
 | |
|              of time, after which they are garbage collected. This allows users to
 | |
|              revert tags to older images in case they accidentally pushed a broken image. It is
 | |
|              highly recommended to have time machine enabled, but it does take a bit more space
 | |
|              in storage.
 | |
|           </p>
 | |
|         </div>
 | |
|         <table class="config-table">
 | |
|           <!-- This `ng-if` true is *required* to create a new scope so that the <form> inside
 | |
|                the config-list-field doesn't try to submit the *outer* form when the Add button
 | |
|                is clicked. This is highly stupid, but until we figure out a better way, such it
 | |
|                shall be.
 | |
|           -->
 | |
|           <tr ng-if="true">
 | |
|             <td>Allowed expiration periods:</td>
 | |
|             <td>
 | |
|               <span class="config-list-field" item-title="Tag Expiration Period" binding="config.TAG_EXPIRATION_OPTIONS" item-pattern="[0-9]+(m|w|h|d|s)"></span>
 | |
|               <div class="help-text">
 | |
|                 The expiration periods allowed for configuration. The default tag expiration *must* be in this list.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Default expiration period:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.DEFAULT_TAG_EXPIRATION"
 | |
|                     pattern="[0-9]+(m|w|h|d|s)"></span>
 | |
|               <div class="help-text">
 | |
|                 The default tag expiration period for all namespaces (users and organizations). Must be expressed in a duration string form: <code>30m</code>, <code>1h</code>, <code>1d</code>, <code>2w</code>.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Allow users to select expiration:</td>
 | |
|             <td>
 | |
|               <div class="config-bool-field" binding="config.FEATURE_CHANGE_TAG_EXPIRATION">
 | |
|                 Enable Expiration Configuration
 | |
|                 <div class="help-text">
 | |
|                   If enabled, users will be able to select the tag expiration duration for the namespace(s) they
 | |
|                   administrate, from the configured list of options.
 | |
|                 </div>
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /Time Machine -->
 | |
| 
 | |
|     <!-- Redis -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <img src="/static/img/redis-small.png"> redis
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|             <p>A <a href="http://redis.io" ng-safenewtab>redis</a> key-value store is required for real-time events and build logs.</p>
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table">
 | |
|           <tr>
 | |
|             <td>Redis Hostname:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="mapped.redis.host"
 | |
|                     placeholder="The redis server hostname"
 | |
|                     pattern="{{ HOSTNAME_REGEX }}"
 | |
|                     validator="validateHostname(value)"></span>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Redis port:</td>
 | |
|             <td>
 | |
|               <span class="config-numeric-field" binding="mapped.redis.port" default-value="6379"></span>
 | |
|               <div class="help-text">
 | |
|                 Access to this port and hostname must be allowed from all hosts running
 | |
|                 the enterprise registry
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Redis password:</td>
 | |
|             <td>
 | |
|               <input class="form-control" type="password" ng-model="mapped.redis.password"
 | |
|                      placeholder="Optional password for connecting to redis">
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /Redis -->
 | |
| 
 | |
|     <!-- Registry Storage -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-download"></i> Registry Storage
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>
 | |
|             Registry images can be stored either locally or in a remote storage system.
 | |
|             <div class="co-alert co-alert-danger">
 | |
|             Do not use local storage for any production configurations.
 | |
|             </div>
 | |
|           </p>
 | |
| 
 | |
|           <div class="config-bool-field feature-storage-replication" binding="config.FEATURE_STORAGE_REPLICATION">
 | |
|             Enable Storage Replication
 | |
|             <div class="help-text">
 | |
|               If enabled, replicates storage to other regions. See <a href="https://tectonic.com/quay-enterprise/docs/latest/geo-replication.html" ng-safenewtab>documentation</a> for more information.
 | |
|             </div>
 | |
|           </div>
 | |
| 
 | |
|           <div class="storage-config" ng-class="$last ? 'last' : ''" ng-repeat="sc in storageConfig">
 | |
|             <table class="config-table">
 | |
|               <tr>
 | |
|                 <td class="non-input">Location ID:</td>
 | |
|                 <td>
 | |
|                   <input class="form-control" ng-if="allowChangeLocationStorageConfig(sc.location)" ng-class="storageConfigError[$index].location ? 'ng-invalid' : ''" ng-model="sc.location" ng-pattern="/^[a-zA-Z0-9_-]+$/" required>
 | |
|                   <div ng-if="!allowChangeLocationStorageConfig(sc.location)">
 | |
|                     {{ sc.location }}
 | |
|                   </div>
 | |
|                   <div class="co-alert co-alert-danger" ng-show="storageConfigError[$index].location">
 | |
|                     {{ storageConfigError[$index].location }}
 | |
|                   </div>
 | |
|                   <div class="input-util" ng-if="allowRemoveStorageConfig(sc.location)"><a class="remove-link" ng-click="removeStorageConfig(sc)">Remove</a></div>
 | |
|                 </td>
 | |
|               </tr>
 | |
| 
 | |
|               <tr ng-if="config.FEATURE_STORAGE_REPLICATION">
 | |
|                 <td class="non-input">Set Default:</td>
 | |
|                 <td>
 | |
|                   <div class="config-bool-field" binding="sc.defaultLocation">
 | |
|                     Replicate to storage engine by default
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
| 
 | |
|               <tr>
 | |
|                 <td class="non-input">Storage Engine:</td>
 | |
|                 <td>
 | |
|                   <select class="form-control" ng-class="storageConfigError[$index].engine ? 'ng-invalid' : ''" ng-model="sc.data[0]">
 | |
|                     <option value="LocalStorage">Locally mounted directory</option>
 | |
|                     <option value="S3Storage">Amazon S3</option>
 | |
|                     <option value="AzureStorage">Azure Blob Storage</option>
 | |
|                     <option value="GoogleCloudStorage">Google Cloud Storage</option>
 | |
|                     <option value="RadosGWStorage">Ceph Object Gateway (RADOS)</option>
 | |
|                     <option value="SwiftStorage">OpenStack Storage (Swift)</option>
 | |
|                     <option value="CloudFrontedS3Storage">CloudFront + Amazon S3</option>
 | |
|                   </select>
 | |
| 
 | |
|                   <div class="co-alert co-alert-danger" ng-if="storageConfigError[$index].engine">
 | |
|                     {{ storageConfigError[$index].engine }}
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
| 
 | |
|               <!-- Fields -->
 | |
|               <tr ng-repeat="field in STORAGE_CONFIG_FIELDS[sc.data[0]]">
 | |
|                 <td>{{ field.title }}:</td>
 | |
|                 <td>
 | |
|                   <span class="config-map-field"
 | |
|                         binding="sc.data[1][field.name]"
 | |
|                         ng-if="field.kind == 'map'"
 | |
|                         keys="field.keys"></span>
 | |
|                   <span class="config-string-field"
 | |
|                         binding="sc.data[1][field.name]"
 | |
|                         placeholder="{{ field.placeholder }}"
 | |
|                         pattern="{{ field.pattern }}"
 | |
|                         ng-if="field.kind == 'text'"
 | |
|                         is-optional="field.optional"></span>
 | |
|                   <span class="config-bool-field"
 | |
|                         binding="sc.data[1][field.name]"
 | |
|                         ng-if="field.kind == 'bool'">
 | |
|                         {{ field.placeholder }}
 | |
|                   </span>
 | |
|                   <span class="config-file-field"
 | |
|                         filename="{{ sc.location + '-' + field.filesuffix }}"
 | |
|                         binding="sc.data[1][field.name]"
 | |
|                         has-file="hasfile['contact-' + sc.location + '-' + field.filesuffix]"
 | |
|                         ng-if="field.kind == 'file'"></span>
 | |
|                   <div ng-if="field.kind == 'option'">
 | |
|                     <select class="form-control" ng-model="sc.data[1][field.name]">
 | |
|                       <option ng-repeat="value in field.values" value="{{ value }}"
 | |
|                               ng-selected="sc.data[1][field.name] == value">{{ value }}</option>
 | |
|                     </select>
 | |
|                   </div>
 | |
|                   <div class="help-text" ng-if="field.help_text">
 | |
|                     {{ field.help_text }}
 | |
|                   </div>
 | |
|                   <div class="help-text" ng-if="field.help_url">
 | |
|                     See <a href="{{ field.help_url }}" ng-safenewtab>Documentation</a> for more information
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|             </table>
 | |
|           </div>
 | |
| 
 | |
|           <div class="add-storage-link" ng-if="canAddStorageConfig()">
 | |
|             <a ng-click="addStorageConfig()">Add Additional Storage Engine</a>
 | |
|           </div>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- Action log archiving -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-archive"></i> Action Log Rotation and Archiving
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>
 | |
|             All actions performed in <span class="registry-name"></span> are automatically logged. These logs are stored in a database table, which can become quite large.
 | |
|             Enabling log rotation and archiving will move all logs older than 30 days into storage.
 | |
|           </p>
 | |
|         </div>
 | |
|         <div class="config-bool-field" binding="config.FEATURE_ACTION_LOG_ROTATION">
 | |
|           Enable Action Log Rotation
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_ACTION_LOG_ROTATION">
 | |
|           <tr>
 | |
|             <td>Storage location:</td>
 | |
|             <td>
 | |
|               <select class="form-control" ng-model="config.ACTION_LOG_ARCHIVE_LOCATION">
 | |
|                 <option ng-repeat="sc in storageConfig" value="{{ sc['location'] }}">{{ sc['location'] }}</option>
 | |
|               </select>
 | |
|               <div class="help-text">
 | |
|                 The storage location in which to place archived action logs. Logs will only be archived to this single location.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Storage path:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.ACTION_LOG_ARCHIVE_PATH"
 | |
|                     placeholder="Path under storage to place archived logs"></span>
 | |
|               <div class="help-text">
 | |
|                 The path under the configured storage engine in which to place the archived logs in JSON form.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Log Rotation Threshold:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.ACTION_LOG_ROTATION_THRESHOLD"
 | |
|                     pattern="[0-9]+(m|w|h|d|s)"></span>
 | |
|               <div class="help-text">
 | |
|                   The number of days after which to archive action logs to storage. Must be expressed in a duration string form: <code>30m</code>, <code>1h</code>, <code>1d</code>, <code>2w</code>.
 | |
|               </div>
 | |
|                 <div class="help-text">
 | |
|                     Note: The rotation threshold should be considered a balancing act between user history and size of database.
 | |
|                 </div>
 | |
|                 <div class="help-text">
 | |
|                     Larger time windows will result in more logs, but give users more history to view.
 | |
|                     Anything less than <code>2w</code> is not recommended.
 | |
|                 </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|     </div>
 | |
| 
 | |
|     <!-- Security Scanner -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-bug"></i> Security Scanner
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>If enabled, all images pushed to Quay will be scanned via the external security scanning service, with vulnerability information available in the UI and API, as well
 | |
|               as async notification support.
 | |
|           </p>
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_SECURITY_SCANNER">
 | |
|           Enable Security Scanning
 | |
|         </div>
 | |
|         <div class="co-alert co-alert-info" ng-if="config.FEATURE_SECURITY_SCANNER" style="margin-top: 20px;">
 | |
|           A scanner compliant with the Quay Security Scanning API must be running to use this feature. Documentation on running <a href="https://github.com/coreos/clair" ng-safenewtab>Clair</a> can be found at <a href="https://tectonic.com/quay-enterprise/docs/latest/clair.html" ng-safenewtab>Running Clair Security Scanner</a>.
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_SECURITY_SCANNER">
 | |
|           <tr>
 | |
|             <td>Authentication Key:</td>
 | |
|             <td>
 | |
|               <span class="config-service-key-field" service-name="{{ config.SECURITY_SCANNER_ISSUER_NAME || 'secscan' }}"></span>
 | |
|               <div class="help-text">
 | |
|                 The security scanning service requires an authorized service key to speak to Quay. Once setup, the key
 | |
|                 can be managed in the Service Keys panel under the Super User Admin Panel.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Security Scanner Endpoint:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.SECURITY_SCANNER_ENDPOINT"
 | |
|                     placeholder="Security Scanner API endpoint (Example: http://myhost:6060)"
 | |
|                     pattern="http(s)?://.+"></span>
 | |
|               <div class="help-text">
 | |
|                 The HTTP URL at which the security scanner is running.
 | |
|               </div>
 | |
|               <div class="co-alert co-alert-info" ng-if="config.SECURITY_SCANNER_ENDPOINT.indexOf('https:') == 0" style="margin-top: 20px;">
 | |
|                 Is the security scanner behind a domain signed with a <strong>self-signed TLS certificate</strong>? If so, please make sure to register your SSL CA in the <a href="#custom-ssl">custom certificates panel</a> above.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- App Registry -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa ci-appcube"></i> Application Registry
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>If enabled, an additional registry API will be available for managing applications (Kubernetes manifests, Helm charts) via the <a href="https://github.com/app-registry">App Registry specification</a>. A great place to get started is to install the <a href="https://github.com/app-registry/appr-helm-plugin">Helm Registry Plugin</a>.
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_APP_REGISTRY">
 | |
|           Enable App Registry
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- BitTorrent pull -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fas fa-cloud-download-alt"></i> BitTorrent-based download
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>If enabled, all images in the registry can be downloaded using the <a href="http://github.com/coreos/quayctl" ng-safenewtab>quayctl</a> tool via the BitTorrent protocol. A JWT-compatible BitTorrent tracker such as <a href="https://tectonic.com/quay-enterprise/docs/latest/running-chihaya.html">Chihaya</a> must be run.
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_BITTORRENT">
 | |
|           Enable BitTorrent downloads
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_BITTORRENT">
 | |
|           <tr>
 | |
|             <td>Announce URL:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.BITTORRENT_ANNOUNCE_URL"
 | |
|                     placeholder="Announce URL for the torrent tracker (Example: http://mytracker/announce)"
 | |
|                     pattern="http(s)?://.+"></span>
 | |
|               <div class="help-text">
 | |
|                 The HTTP URL at which the torrents should be announced. A JWT-compatible tracker such as <a href="https://github.com/chihaya/chihaya" ng-safenewtab>Chihaya</a> must be run to ensure proper security. Documentation on running Chihaya with
 | |
|                 this support can be found at <a href="https://tectonic.com/quay-enterprise/docs/latest/running-chihaya.html">Running Chihaya for Quay Enterprise</a>.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- ACI Conversion -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa rocket-icon" style="width: 20px; height: 20px; background-size: cover; vertical-align: middle;"></i> <a href="http://github.com/coreos/rkt" ng-safenewtab>rkt</a> Conversion
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>If enabled, all images in the registry can be fetched via <code>rkt fetch</code> or any other <a href="https://github.com/appc/spec/blob/master/spec/discovery.md" ng-safenewtab>AppC discovery</a>-compliant implementation.</p>
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_ACI_CONVERSION">
 | |
|           Enable ACI Conversion
 | |
|         </div>
 | |
| 
 | |
|         <div class="co-alert co-alert-info" ng-if="config.FEATURE_ACI_CONVERSION" style="margin-top: 20px;">
 | |
|           Documentation on generating these keys can be found at <a href="https://tectonic.com/quay-enterprise/docs/latest/aci-signing-keys.html" ng-safenewtab>Generating ACI Signing Keys</a>.
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_ACI_CONVERSION">
 | |
|           <tr>
 | |
|             <td class="non-input">GPG2 Public Key File:</td>
 | |
|             <td>
 | |
|               <span class="config-file-field" filename="signing-public.gpg" has-file="hasfile.gpgSigningPublic"></span>
 | |
|               <div class="help-text">
 | |
|                 The certificate must be in PEM format.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">GPG2 Private Key File:</td>
 | |
|             <td>
 | |
|               <span class="config-file-field" filename="signing-private.gpg" has-file="hasfile.gpgSigningPrivate"></span>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">GPG2 Private Key Name:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.GPG2_PRIVATE_KEY_NAME"
 | |
|                     placeholder="Name of the private key in the private key file (Example: EAB32227)"></span>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div>
 | |
| 
 | |
|     <!-- E-mail -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-envelope"></i> E-mail
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>Valid e-mail server configuration is required for notification e-mails and the ability of
 | |
|           users to reset their passwords.</p>
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_MAILING">
 | |
|           Enable E-mails
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_MAILING">
 | |
|           <tr>
 | |
|             <td>SMTP Server:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.MAIL_SERVER"
 | |
|                     placeholder="SMTP server for sending e-mail"
 | |
|                     pattern="{{ HOSTNAME_REGEX }}"
 | |
|                     validator="validateHostname(value)">></span>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>SMTP Server Port:</td>
 | |
|             <td>
 | |
|               <span class="config-numeric-field" binding="config.MAIL_PORT"
 | |
|                     default-value="587"></span>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>TLS:</td>
 | |
|             <td>
 | |
|               <div class="config-bool-field" binding="config.MAIL_USE_TLS">
 | |
|                 Require TLS
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Mail Sender:</td>
 | |
|             <td>
 | |
|               <input class="form-control" type="email" ng-model="config.MAIL_DEFAULT_SENDER"
 | |
|                      placeholder="E-mail address"></span>
 | |
|               <div class="help-text">
 | |
|                 E-mail address from which all e-mails are sent. If not specified,
 | |
|                 <code>support@quay.io</code> will be used.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Authentication:</td>
 | |
|             <td>
 | |
|               <div class="config-bool-field" binding="config.MAIL_USE_AUTH">
 | |
|                 Requires Authentication
 | |
|               </div>
 | |
| 
 | |
|               <table class="config-table" ng-if="config.MAIL_USE_AUTH">
 | |
|                 <tr>
 | |
|                   <td>Username:</td>
 | |
|                   <td>
 | |
|                     <span class="config-string-field" binding="config.MAIL_USERNAME"
 | |
|                           placeholder="Username for authentication"></span>
 | |
|                   </td>
 | |
|                 </tr>
 | |
|                 <tr>
 | |
|                   <td>Password:</td>
 | |
|                   <td>
 | |
|                     <input class="form-control" type="password"
 | |
|                           ng-model="config.MAIL_PASSWORD"
 | |
|                           placeholder="Password for authentication"></span>
 | |
|                   </td>
 | |
|                 </tr>
 | |
|               </table>
 | |
|             </td>
 | |
|           </tr>
 | |
| 
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /E-mail -->
 | |
| 
 | |
|     <!-- Internal Authentication -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-users"></i> Internal Authentication
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>
 | |
|             Authentication for the registry can be handled by either the registry itself, LDAP, Keystone, or external JWT endpoint.
 | |
|           </p>
 | |
|           <p>
 | |
|             Additional <strong>external</strong> authentication providers (such as GitHub) can be used in addition for <strong>login into the UI</strong>.
 | |
|           </p>
 | |
|         </div>
 | |
| 
 | |
|         <div ng-if="config.AUTHENTICATION_TYPE != 'AppToken'">
 | |
|           <div class="co-alert co-alert-warning" ng-if="config.AUTHENTICATION_TYPE != 'Database' && !config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH">
 | |
|             It is <strong>highly recommended</strong> to require encrypted client passwords. External passwords used in the Docker client will be stored in <strong>plaintext</strong>!
 | |
|             <a ng-click="config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH = true">Enable this requirement now</a>.
 | |
|           </div>
 | |
| 
 | |
|           <div class="co-alert co-alert-success" ng-if="config.AUTHENTICATION_TYPE != 'Database' && config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH">
 | |
|             Note: The "Require Encrypted Client Passwords" feature is currently enabled which will
 | |
|             prevent passwords from being saved as plaintext by the Docker client.
 | |
|           </div>
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" style="margin-bottom: 20px;">
 | |
|           <tr>
 | |
|             <td class="non-input">Authentication:</td>
 | |
|             <td>
 | |
|               <select class="form-control" ng-model="config.AUTHENTICATION_TYPE">
 | |
|                 <option value="Database">Local Database</option>
 | |
|                 <option value="LDAP">LDAP</option>
 | |
|                 <option value="Keystone">Keystone (OpenStack Identity)</option>
 | |
|                 <option value="JWT">JWT Custom Authentication</option>
 | |
|                 <option value="AppToken" ng-if="config.FEATURE_APP_SPECIFIC_TOKENS">External Application Token</option>
 | |
|               </select>
 | |
|             </td>
 | |
|           </tr>
 | |
| 
 | |
|           <tr ng-if="config.AUTHENTICATION_TYPE == 'LDAP' || config.AUTHENTICATION_TYPE == 'Keystone'">
 | |
|             <td>Team synchronization:</td>
 | |
|             <td>
 | |
|               <div class="config-bool-field" binding="config.FEATURE_TEAM_SYNCING">
 | |
|                 Enable Team Synchronization Support
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                 If enabled, organization administrators who are also superusers can set teams to have their membership synchronized with a backing group in {{ config.AUTHENTICATION_TYPE }}.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr ng-if="(config.AUTHENTICATION_TYPE == 'LDAP' || config.AUTHENTICATION_TYPE == 'Keystone') && config.FEATURE_TEAM_SYNCING">
 | |
|           <td>Resynchronization duration:</td>
 | |
|           <td>
 | |
|             <span class="config-string-field" binding="config.TEAM_RESYNC_STALE_TIME"
 | |
|                   pattern="[0-9]+(m|h|d|s)"></span>
 | |
|             <div class="help-text">
 | |
|             The duration before a team must be re-synchronized. Must be expressed in a duration string form: <code>30m</code>, <code>1h</code>, <code>1d</code>.
 | |
|             </div>
 | |
|           </td>
 | |
|           </tr>
 | |
|           <tr ng-if="(config.AUTHENTICATION_TYPE == 'LDAP' || config.AUTHENTICATION_TYPE == 'Keystone') && config.FEATURE_TEAM_SYNCING">
 | |
|           <td>Self-service team syncing setup:</td>
 | |
|           <td>
 | |
|             <div class="co-alert co-alert-warning" style="margin-bottom: 20px;">If enabled, this feature will allow *any organization administrator* to read the membership of any {{ config.AUTHENTICATION_TYPE }} group.</div>
 | |
|             <div class="config-bool-field" binding="config.FEATURE_NONSUPERUSER_TEAM_SYNCING_SETUP">
 | |
|               Allow non-superusers to enable and manage team syncing
 | |
|             </div>
 | |
|             <div class="help-text">
 | |
|             If enabled, non-superusers will be able to enable and manage team sycning on teams under organizations in which they are administrators.
 | |
|             </div>
 | |
|           </td>
 | |
|           </tr>
 | |
|         </table>
 | |
| 
 | |
|         <!--  Keystone Authentication -->
 | |
|         <table class="config-table" ng-if="config.AUTHENTICATION_TYPE == 'Keystone'">
 | |
|           <tr>
 | |
|             <td>Keystone API Version:</td>
 | |
|             <td>
 | |
|               <select ng-model="config.KEYSTONE_AUTH_VERSION">
 | |
|                 <option value="2">2.0</option>
 | |
|                 <option value="3">V3</option>
 | |
|               </select>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Keystone Authentication URL:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.KEYSTONE_AUTH_URL"
 | |
|                     pattern="http(s)?://.+"></span>
 | |
|               <div class="help-text">
 | |
|               The URL (starting with http or https) of the Keystone Server endpoint for auth.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Keystone Administrator Username:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.KEYSTONE_ADMIN_USERNAME"></span>
 | |
|               <div class="help-text">
 | |
|                  The username for the Keystone admin.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Keystone Administrator Password:</td>
 | |
|             <td>
 | |
|               <input type="password" ng-model="config.KEYSTONE_ADMIN_PASSWORD"
 | |
|                      class="form-control" required></span>
 | |
|               <div class="help-text">
 | |
|                  The password for the Keystone admin.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Keystone Administrator Tenant:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.KEYSTONE_ADMIN_TENANT"></span>
 | |
|               <div class="help-text">
 | |
|                 The tenant (project/group) that contains the administrator user.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
| 
 | |
|         <!-- JWT Custom Authentication -->
 | |
|         <div class="co-alert co-alert-info" ng-if="config.AUTHENTICATION_TYPE == 'JWT'">
 | |
|           JSON Web Token authentication allows your organization to provide an HTTP endpoint that
 | |
|           verifies user credentials on behalf of <span class="registry-name"></span>.
 | |
|           <br>
 | |
|           Documentation
 | |
|           on the API required can be found here: <a href="https://github.com/coreos/jwt-auth-example" ng-safenewtab>https://github.com/coreos/jwt-auth-example</a>.
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.AUTHENTICATION_TYPE == 'JWT'">
 | |
|           <tr>
 | |
|             <td>Authentication Issuer:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.JWT_AUTH_ISSUER"></span>
 | |
|               <div class="help-text">
 | |
|                 The id of the issuer signing the JWT token. Must be unique to your organization.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Public Key:</td>
 | |
|             <td>
 | |
|               <span class="config-file-field" filename="jwt-authn.cert" has-file="hasfile.JWTCert"></span>
 | |
|               <div class="help-text">
 | |
|                 A certificate containing the public key portion of the key pair used to sign
 | |
|                 the JSON Web Tokens. This file must be in PEM format.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>User Verification Endpoint:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.JWT_VERIFY_ENDPOINT"
 | |
|                     pattern="http(s)?://.+"></span>
 | |
|               <div class="help-text">
 | |
|               The URL (starting with http or https) on the JWT authentication server for verifying username and password credentials.
 | |
|               </div>
 | |
| 
 | |
|               <div class="help-text" style="margin-top: 6px;">
 | |
|               Credentials will be sent in the <code>Authorization</code> header as Basic Auth, and this endpoint should return <code>200 OK</code> on success (or a <code>4**</code> otherwise).
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>User Query Endpoint:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.JWT_QUERY_ENDPOINT"
 | |
|                     pattern="http(s)?://.+" is-optional="true"></span>
 | |
|               <div class="help-text">
 | |
|               The URL (starting with http or https) on the JWT authentication server for looking up
 | |
|               users based on a prefix query. This is optional.
 | |
|               </div>
 | |
| 
 | |
|               <div class="help-text" style="margin-top: 6px;">
 | |
|               The prefix query will be sent as a query parameter with name <code>query</code>.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>User Lookup Endpoint:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.JWT_GETUSER_ENDPOINT"
 | |
|                     pattern="http(s)?://.+" is-optional="true"></span>
 | |
|               <div class="help-text">
 | |
|               The URL (starting with http or https) on the JWT authentication server for looking up
 | |
|               a user by username or email address.
 | |
|               </div>
 | |
| 
 | |
|               <div class="help-text" style="margin-top: 6px;">
 | |
|               The username or email address will be sent as a query parameter with name <code>username</code>.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
| 
 | |
|         <!-- LDAP Authentication -->
 | |
|         <table class="config-table" ng-if="config.AUTHENTICATION_TYPE == 'LDAP'">
 | |
|           <tr>
 | |
|             <td>LDAP URI:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.LDAP_URI"
 | |
|                     pattern="ldap(s)?://.+"></span>
 | |
|               <div class="help-text">
 | |
|               The full LDAP URI, including the ldap:// or ldaps:// prefix.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Base DN:</td>
 | |
|             <td>
 | |
|               <span class="config-string-list-field" item-title="DN piece" item-delimiter="," binding="config.LDAP_BASE_DN"></span>
 | |
|               <div class="help-text">
 | |
|               A Distinguished Name path which forms the base path for looking up all LDAP records.
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                 Example: dc=my,dc=domain,dc=com
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>User Relative DN:</td>
 | |
|             <td>
 | |
|               <span class="config-string-list-field" item-title="RDN piece" item-delimiter="," binding="config.LDAP_USER_RDN"></span>
 | |
|               <div class="help-text">
 | |
|               A Distinguished Name path which forms the base path for looking up all user LDAP records,
 | |
|               relative to the Base DN defined above.
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                 Example: ou=employees
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Secondary User Relative DNs:</td>
 | |
|             <td>
 | |
|               <span class="config-list-field" item-title="RDN" binding="config.LDAP_SECONDARY_USER_RDNS"></span>
 | |
|               <div class="help-text">
 | |
|               A list of Distinguished Name path(s) which forms the secondary base path(s) for
 | |
|               looking up all user LDAP records, relative to the Base DN defined above. These path(s)
 | |
|               will be tried if the user is not found via the primary relative DN.
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                 Example: [ou=employees]
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Administrator DN:</td>
 | |
|             <td><span class="config-string-field" binding="config.LDAP_ADMIN_DN"></span>
 | |
|               <div class="help-text">
 | |
|               The Distinguished Name for the Administrator account. This account must be able to login and view the records for all user accounts.
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                 Example: uid=admin,ou=employees,dc=my,dc=domain,dc=com
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Administrator DN Password:</td>
 | |
|             <td>
 | |
|               <div class="co-alert co-alert-warning" style="margin-bottom: 10px;">
 | |
|                 Note: This will be stored in
 | |
|                 <strong>plaintext</strong> inside the config.yaml, so setting up a dedicated account or using
 | |
|                 <a href="http://tools.ietf.org/id/draft-stroeder-hashed-userpassword-values-01.html" ng-safenewtab>a password hash</a> is <strong>highly</strong> recommended.
 | |
|               </div>
 | |
|               <input class="form-control" type="password" ng-model="config.LDAP_ADMIN_PASSWD">
 | |
|               <div class="help-text">
 | |
|                The password for the Administrator DN.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>UID Attribute:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.LDAP_UID_ATTR" default-value="uid"></span>
 | |
|               <div class="help-text">
 | |
|                The name of the property field in your LDAP user records that stores your
 | |
|                users' username. Typically "uid".
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Mail Attribute:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.LDAP_EMAIL_ATTR" default-value="mail"></span>
 | |
|               <div class="help-text">
 | |
|                The name of the property field in your LDAP user records that stores your
 | |
|                users' e-mail address(es). Typically "mail".
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr ng-if="config.LDAP_URI.indexOf('ldaps://') == 0">
 | |
|             <td class="non-input">Custom TLS Certificate:</td>
 | |
|             <td>
 | |
|               <span class="config-file-field" filename="ldap.crt" has-file="hasfile.LDAPTLSCert"></span>
 | |
|               <div class="help-text">
 | |
|                 If specified, the certificate (in PEM format) for the LDAP TLS connection.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr ng-if="config.LDAP_URI.indexOf('ldaps://') == 0">
 | |
|             <td class="non-input">Allow insecure:</td>
 | |
|             <td>
 | |
|               <div class="config-bool-field" binding="config.LDAP_ALLOW_INSECURE_FALLBACK">
 | |
|                 Allow fallback to non-TLS connections
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                 If enabled, LDAP will fallback to <strong>insecure non-TLS connections</strong> if TLS does not succeed.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- / Internal Authentication -->
 | |
| 
 | |
|     <div class="co-panel"> <!-- External Authentication -->
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-id-card"></i> External Authorization (OAuth)
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <!-- GitHub Authentication -->
 | |
|         <div class="co-panel">
 | |
|           <div class="co-panel-heading">
 | |
|             <i class="fab fa-github"></i> GitHub (Enterprise) Authentication
 | |
|           </div>
 | |
|           <div class="co-panel-body">
 | |
|             <div class="description">
 | |
|               <p>
 | |
|                 If enabled, users can use GitHub or GitHub Enterprise to authenticate to the registry.
 | |
|               </p>
 | |
|               <p>
 | |
|                 <strong>Note:</strong> A registered GitHub (Enterprise) OAuth application is required.
 | |
|                 View instructions on how to
 | |
|                 <a href="https://coreos.com/docs/enterprise-registry/github-app/" ng-safenewtab>
 | |
|                   Create an OAuth Application in GitHub
 | |
|                 </a>
 | |
|               </p>
 | |
|             </div>
 | |
| 
 | |
|             <div class="config-bool-field" binding="config.FEATURE_GITHUB_LOGIN">
 | |
|               Enable GitHub Authentication
 | |
|             </div>
 | |
| 
 | |
|             <div class="co-alert co-alert-warning" ng-if="config.FEATURE_GITHUB_LOGIN && config.AUTHENTICATION_TYPE && config.AUTHENTICATION_TYPE != 'Database' && config.AUTHENTICATION_TYPE != 'AppToken' && !config.GITHUB_LOGIN_CONFIG.LOGIN_BINDING_FIELD">
 | |
|               Warning: This provider is not bound to your <strong>{{ config.AUTHENTICATION_TYPE }}</strong> authentication. Logging in via this provider will create a <strong><span class="registry-name"></span>-only user</strong>, which is not the recommended approach. It is <strong>highly</strong> recommended to choose a "Binding Field" below.
 | |
|             </div>
 | |
| 
 | |
|             <table class="config-table" ng-if="config.FEATURE_GITHUB_LOGIN">
 | |
|               <tr>
 | |
|                 <td>GitHub:</td>
 | |
|                 <td>
 | |
|                   <select class="form-control" ng-model="mapped.GITHUB_LOGIN_KIND">
 | |
|                     <option value="hosted">GitHub.com</option>
 | |
|                     <option value="enterprise">GitHub Enterprise</option>
 | |
|                   </select>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr ng-if="mapped.GITHUB_LOGIN_KIND == 'enterprise'">
 | |
|                 <td>GitHub Endpoint:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field"
 | |
|                         binding="config.GITHUB_LOGIN_CONFIG.GITHUB_ENDPOINT"
 | |
|                         placeholder="https://my.githubserver"
 | |
|                         pattern="{{ GITHOST_REGEX }}">
 | |
|                   </span>
 | |
|                   <div class="help-text">
 | |
|                     The GitHub Enterprise endpoint. Must start with http:// or https://.
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>OAuth Client ID:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field" binding="config.GITHUB_LOGIN_CONFIG.CLIENT_ID">
 | |
|                   </span>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>OAuth Client Secret:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field" binding="config.GITHUB_LOGIN_CONFIG.CLIENT_SECRET">
 | |
|                   </span>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Organization Filtering:</td>
 | |
|                 <td>
 | |
|                   <div class="config-bool-field" binding="config.GITHUB_LOGIN_CONFIG.ORG_RESTRICT">
 | |
|                     Restrict By Organization Membership
 | |
|                   </div>
 | |
| 
 | |
|                   <div class="help-text" style="margin-bottom: 20px;">
 | |
|                     If enabled, only members of specified GitHub
 | |
|                     <span ng-if="mapped.GITHUB_LOGIN_KIND == 'enterprise'">Enterprise</span> organizations will be allowed to login via GitHub
 | |
|                     <span ng-if="mapped.GITHUB_LOGIN_KIND == 'enterprise'">Enterprise</span>.
 | |
|                   </div>
 | |
| 
 | |
|                   <span class="config-list-field"
 | |
|                         item-title="Organization ID"
 | |
|                         binding="config.GITHUB_LOGIN_CONFIG.ALLOWED_ORGANIZATIONS"
 | |
|                         ng-if="config.GITHUB_LOGIN_CONFIG.ORG_RESTRICT">
 | |
|                   </span>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr ng-if="config.AUTHENTICATION_TYPE != 'Database' && config.AUTHENTICATION_TYPE != 'AppToken'">
 | |
|                 <td>Binding Field:</td>
 | |
|                 <td>
 | |
|                   <select class="form-control" ng-model="config.GITHUB_LOGIN_CONFIG.LOGIN_BINDING_FIELD">
 | |
|                     <option value="">(None)</option>
 | |
|                     <option value="sub">Subject (User ID)</option>
 | |
|                     <option value="username">Username</option>
 | |
|                     <option value="email">E-mail address</option>
 | |
|                   </select>
 | |
|                   <div class="help-text">
 | |
|                     If selected, when a user logs in via this provider, they will be automatically bound to their user in <strong>{{ config.AUTHENTICATION_TYPE }}</strong> by matching the selected field from the provider to the associated user in {{ config.AUTHENTICATION_TYPE }}.
 | |
|                   </div>
 | |
|                   <div class="help-text">
 | |
|                     For example, selecting <code>Subject</code> here with a backing authentication system of LDAP means that a user logging in via this provider will also be bound to their user in LDAP by username.
 | |
|                   </div>
 | |
|                   <div class="help-text">
 | |
|                     If none selected, a <strong>user unique to <span class="registry-name"></span></strong> will be created on initial login with this provider. <strong>This is not the recommended setup.</strong>
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|             </table>
 | |
|           </div>
 | |
|         </div> <!-- /GitHub Authentication -->
 | |
| 
 | |
|         <!-- Google Authentication -->
 | |
|         <div class="co-panel">
 | |
|           <div class="co-panel-heading">
 | |
|             <i class="fab fa-google"></i> Google Authentication
 | |
|           </div>
 | |
|           <div class="co-panel-body">
 | |
|             <div class="description">
 | |
|               <p>
 | |
|                 If enabled, users can use Google to authenticate to the registry.
 | |
|               </p>
 | |
|               <p>
 | |
|                 <strong>Note:</strong> A registered Google OAuth application is required.
 | |
|                 Visit the
 | |
|                 <a href="https://console.developers.google.com" ng-safenewtab>
 | |
|                   Google Developer Console
 | |
|                 </a>
 | |
|                 to register an application.
 | |
|               </p>
 | |
|             </div>
 | |
| 
 | |
|             <div class="config-bool-field" binding="config.FEATURE_GOOGLE_LOGIN">
 | |
|               Enable Google Authentication
 | |
|             </div>
 | |
| 
 | |
|             <div class="co-alert co-alert-warning" ng-if="config.FEATURE_GOOGLE_LOGIN && config.AUTHENTICATION_TYPE && config.AUTHENTICATION_TYPE != 'Database' && config.AUTHENTICATION_TYPE != 'AppToken' && !config.GOOGLE_LOGIN_CONFIG.LOGIN_BINDING_FIELD">
 | |
|               Warning: This provider is not bound to your <strong>{{ config.AUTHENTICATION_TYPE }}</strong> authentication. Logging in via this provider will create a <strong><span class="registry-name"></span>-only user</strong>, which is not the recommended approach. It is <strong>highly</strong> recommended to choose a "Binding Field" below.
 | |
|             </div>
 | |
| 
 | |
|             <table class="config-table" ng-if="config.FEATURE_GOOGLE_LOGIN">
 | |
|               <tr>
 | |
|                 <td>OAuth Client ID:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field" binding="config.GOOGLE_LOGIN_CONFIG.CLIENT_ID">
 | |
|                   </span>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>OAuth Client Secret:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field" binding="config.GOOGLE_LOGIN_CONFIG.CLIENT_SECRET">
 | |
|                   </span>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr ng-if="config.AUTHENTICATION_TYPE != 'Database' && config.AUTHENTICATION_TYPE != 'AppToken'">
 | |
|                 <td>Binding Field:</td>
 | |
|                 <td>
 | |
|                   <select class="form-control" ng-model="config.GOOGLE_LOGIN_CONFIG.LOGIN_BINDING_FIELD">
 | |
|                     <option value="">(None)</option>
 | |
|                     <option value="sub">Subject (User ID)</option>
 | |
|                     <option value="username">Username</option>
 | |
|                     <option value="email">E-mail address</option>
 | |
|                   </select>
 | |
|                   <div class="help-text">
 | |
|                     If selected, when a user logs in via this provider, they will be automatically bound to their user in <strong>{{ config.AUTHENTICATION_TYPE }}</strong> by matching the selected field from the provider to the associated user in {{ config.AUTHENTICATION_TYPE }}.
 | |
|                   </div>
 | |
|                   <div class="help-text">
 | |
|                     For example, selecting <code>Subject</code> here with a backing authentication system of LDAP means that a user logging in via this provider will also be bound to their user in LDAP by username.
 | |
|                   </div>
 | |
|                   <div class="help-text">
 | |
|                     If none selected, a <strong>user unique to <span class="registry-name"></span></strong> will be created on initial login with this provider. <strong>This is not the recommended setup.</strong>
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|             </table>
 | |
|           </div>
 | |
|         </div> <!-- /Google Authentication -->
 | |
| 
 | |
|         <!-- Custom OIDC providers -->
 | |
|         <div class="co-panel" ng-repeat="provider in getOIDCProviders(config)">
 | |
|           <div class="co-panel-heading">
 | |
|             <span class="icon-image-view" value="{{ config[provider]['SERVICE_ICON'] || 'fa-user-circle' }}" style="margin-right: 6px;"></span>
 | |
|             {{ config[provider]['SERVICE_NAME'] || (getOIDCProviderId(provider) + ' Authentication') }}
 | |
|             <span style="display: inline-block; margin-left: 10px">(<a href="javascript:void(0)" ng-click="removeOIDCProvider(provider)">Delete</a>)</span>
 | |
|           </div>
 | |
|           <div class="co-panel-body">
 | |
|             <div class="co-alert co-alert-warning" ng-if="config.AUTHENTICATION_TYPE && config.AUTHENTICATION_TYPE != 'Database' && config.AUTHENTICATION_TYPE != 'AppToken' && !(config[provider].LOGIN_BINDING_FIELD)">
 | |
|               Warning: This OIDC provider is not bound to your <strong>{{ config.AUTHENTICATION_TYPE }}</strong> authentication. Logging in via this provider will create a <strong><span class="registry-name"></span>-only user</strong>, which is not the recommended approach. It is <strong>highly</strong> recommended to choose a "Binding Field" below.
 | |
|             </div>
 | |
| 
 | |
|             <table class="config-table">
 | |
|               <tr>
 | |
|                 <td class="non-input">Service ID:</td>
 | |
|                 <td>
 | |
|                   <code>{{ getOIDCProviderId(provider) }}</code>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>OIDC Server:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field"
 | |
|                         binding="config[provider].OIDC_SERVER"
 | |
|                         placeholder="https://path/to/oidc/compliant/server"
 | |
|                         pattern="https://.+">
 | |
|                   </span>
 | |
|                   <div class="help-text">
 | |
|                     The URL of an OIDC-compliant server.
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Client ID:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field" binding="config[provider].CLIENT_ID"></span>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Client Secret:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field" binding="config[provider].CLIENT_SECRET"></span>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Service Name:</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field"
 | |
|                         binding="config[provider].SERVICE_NAME"
 | |
|                         placeholder="My Authentication Service">
 | |
|                   </span>
 | |
|                   <div class="help-text">
 | |
|                     The user friendly name to display for the service on the login page.
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Service Icon (optional):</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field"
 | |
|                         binding="config[provider].SERVICE_ICON"
 | |
|                         placeholder="URL of the icon to use for this service OR a font awesome CSS name"
 | |
|                         is-optional="true">
 | |
|                   </span>
 | |
|                   <div class="help-text">
 | |
|                     If specified, the icon to display for this login service on the login page. Can be either a URL to an icon or a CSS class name from <a href="http://fontawesome.io" ng-safenewtab>Font Awesome</a>
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Verified E-mail Address Claim (optional):</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field"
 | |
|                         binding="config[provider].VERIFIED_EMAIL_CLAIM_NAME"
 | |
|                         placeholder="User information JWT claim that contains the verified e-mail"
 | |
|                         is-optional="true">
 | |
|                   </span>
 | |
|                   <div class="help-text">
 | |
|                     If specified, the claim in the User Information JWT that contains the verified e-mail address for the user.
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Preferred Username Claim (optional):</td>
 | |
|                 <td>
 | |
|                   <span class="config-string-field"
 | |
|                         binding="config[provider].PREFERRED_USERNAME_CLAIM_NAME"
 | |
|                         placeholder="User information JWT claim that contains the preferred username"
 | |
|                         is-optional="true">
 | |
|                   </span>
 | |
|                   <div class="help-text">
 | |
|                     If specified, the claim in the User Information JWT that contains the preferred username for the user.
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr ng-if="config.AUTHENTICATION_TYPE != 'Database' && config.AUTHENTICATION_TYPE != 'AppToken'">
 | |
|                 <td>Binding Field:</td>
 | |
|                 <td>
 | |
|                   <select class="form-control" ng-model="config[provider].LOGIN_BINDING_FIELD">
 | |
|                     <option value="">(None)</option>
 | |
|                     <option value="sub">Subject (User ID)</option>
 | |
|                     <option value="username">Username</option>
 | |
|                     <option value="email">E-mail address</option>
 | |
|                   </select>
 | |
|                   <div class="help-text">
 | |
|                     If selected, when a user logs in via this OIDC provider, they will be automatically bound to their user in <strong>{{ config.AUTHENTICATION_TYPE }}</strong> by matching the selected field from the OIDC provider to the associated user in {{ config.AUTHENTICATION_TYPE }}.
 | |
|                   </div>
 | |
|                   <div class="help-text">
 | |
|                     For example, selecting <code>Subject</code> here with a backing authentication system of LDAP means that a user logging in via this OIDC provider will also be bound to their user in LDAP by username.
 | |
|                   </div>
 | |
|                   <div class="help-text">
 | |
|                     If none selected, a <strong>user unique to <span class="registry-name"></span></strong> will be created on initial login with this OIDC provider. <strong>This is not the recommended setup.</strong>
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|               <tr>
 | |
|                 <td>Login Scopes:</td>
 | |
|                 <td>
 | |
|                   <span class="config-list-field" item-title="Login Scope" binding="config[provider].LOGIN_SCOPES"></span>
 | |
|                   <div class="help-text">
 | |
|                     If specified, the scopes to send to the OIDC provider when performing the login flow. Note that, <strong>if specified</strong>, these scopes will
 | |
|                     <strong>override</strong> those set by default, so this list <strong>must</strong> include a scope for OpenID Connect
 | |
|                     (typically the <code>openid</code> scope) or this provider will fail.
 | |
|                   </div>
 | |
|                 </td>
 | |
|               </tr>
 | |
|             </table>
 | |
|             <div>
 | |
|               <h4>Callback URLs for this service:</h4>
 | |
|               <ul>
 | |
|                 <li><code>{{ mapped.TLS_SETTING == 'none' ? 'http' : 'https' }}://{{ config.SERVER_HOSTNAME || '(configure server hostname)' }}/oauth2/{{ getOIDCProviderId(provider).toLowerCase() }}/callback</code></li>
 | |
|                 <li><code>{{ mapped.TLS_SETTING == 'none' ? 'http' : 'https' }}://{{ config.SERVER_HOSTNAME || '(configure server hostname)' }}/oauth2/{{ getOIDCProviderId(provider).toLowerCase() }}/callback/attach</code></li>
 | |
|                 <li><code>{{ mapped.TLS_SETTING == 'none' ? 'http' : 'https' }}://{{ config.SERVER_HOSTNAME || '(configure server hostname)' }}/oauth2/{{ getOIDCProviderId(provider).toLowerCase() }}/callback/cli</code></li>
 | |
|               </ul>
 | |
|              </div>
 | |
|             </div>
 | |
|         </div>
 | |
| 
 | |
|         <!-- Add Provider -->
 | |
|         <a class="btn btn-default" ng-click="addOIDCProvider()" style="margin-right: 6px;">Add OIDC Provider</a>
 | |
|         <a href="http://openid.net/connect/" ng-safenewtab>What is OIDC?</a>
 | |
|       </div>
 | |
|     </div> <!-- /External Authentication -->
 | |
| 
 | |
|     <!-- Access settings -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-user-circle"></i> Access Settings
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>Various settings around access and authentication to the registry.</p>
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table">
 | |
|           <tr>
 | |
|             <td class="non-input">Basic Credentials Login:</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_DIRECT_LOGIN" ng-if="getOIDCProviders(config).length || config.FEATURE_GITHUB_LOGIN || config.FEATURE_GOOGLE_LOGIN">
 | |
|                 Login to User Interface via credentials
 | |
|               </div>
 | |
|               <div ng-if="!getOIDCProviders(config).length && !config.FEATURE_GITHUB_LOGIN && !config.FEATURE_GOOGLE_LOGIN">
 | |
|                 <div ng-if="!config.FEATURE_DIRECT_LOGIN" class="co-alert co-alert-danger">
 | |
|                   Login to User Interface via credentials must be enabled. <a ng-click="enableFeature(config, 'FEATURE_DIRECT_LOGIN')">Click here to enable</a>.
 | |
|                 </div>
 | |
|                 <div ng-if="config.FEATURE_DIRECT_LOGIN">
 | |
|                   Login to User Interface via credentials is <strong>enabled</strong> (requires at least one OIDC provider to disable)
 | |
|                 </div>
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                  If enabled, users will be able to login to the <strong>user interface</strong> via their username and password credentials.
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                  If <strong>disabled</strong>, users will only be able to login to the <strong>user interface</strong> via one of the configured External Authentication providers.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">External Application tokens</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_APP_SPECIFIC_TOKENS">
 | |
|                 Allow external application tokens
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                   If enabled, users will be able to generate external application tokens for use on the Docker and rkt CLI. Note
 | |
|                   that these tokens will <strong>not be required</strong> unless "App Token" is chosen as the Internal Authentication method above.
 | |
|                </div>
 | |
|              </td>
 | |
|           </tr>
 | |
|           <tr ng-if="config.FEATURE_APP_SPECIFIC_TOKENS">
 | |
|               <td>External application token expiration</td>
 | |
|               <td colspan="2">
 | |
|                 <span class="config-string-field" binding="config.APP_SPECIFIC_TOKEN_EXPIRATION"
 | |
|                       pattern="[0-9]+(m|w|h|d|s)" is-optional="true"></span>              
 | |
|                 <div class="help-text">
 | |
|                   The expiration time for user generated external application tokens. If none, tokens will never expire.
 | |
|                 </div>
 | |
|                </td>
 | |
|             </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">Anonymous Access:</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_ANONYMOUS_ACCESS">
 | |
|                 Enable Anonymous Access
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                  If enabled, public repositories and search can be accessed by anyone that can
 | |
|                  reach the registry, even if they are not authenticated. Disable to only allow
 | |
|                  authenticated users to view and pull "public" resources.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">User Creation:</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_USER_CREATION">
 | |
|                 Enable Open User Creation
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                  If enabled, user accounts can be created by anyone (unless restricted below to invited users).
 | |
|                  Users can always be created in the users panel in this superuser tool, even if this feature is disabled.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr ng-show="config.FEATURE_USER_CREATION && config.FEATURE_MAILING">
 | |
|             <td class="non-input">Invite-only User Creation:</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_INVITE_ONLY_USER_CREATION">
 | |
|                 Enable Invite-only User Creation
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                   If enabled, user accounts can only be created when a user has been invited, by e-mail address, to join a team.
 | |
|                   Users can always be created in the users panel in this superuser tool, even if this feature is enabled.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">Encrypted Client Password:</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH">
 | |
|                 Require Encrypted Client Passwords
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                  If enabled, users will not be able to login from the Docker command
 | |
|                  line with a non-encrypted password and must generate an encrypted
 | |
|                  password to use.
 | |
|               </div>
 | |
|               <div class="help-text" ng-if="config.AUTHENTICATION_TYPE != 'Database'">
 | |
|                 This feature is <strong>highly recommended</strong> for setups with external authentication, as Docker currently stores passwords in <strong>plaintext</strong> on user's machines.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td class="non-input">Prefix username autocompletion:</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_PARTIAL_USER_AUTOCOMPLETE">
 | |
|                 Allow prefix username autocompletion
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                  If disabled, autocompletion for users will only match on exact usernames.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr ng-show="config.FEATURE_MAILING">
 | |
|             <td class="non-input">Team Invitations:</td>
 | |
|             <td colspan="2">
 | |
|               <div class="config-bool-field" binding="config.FEATURE_REQUIRE_TEAM_INVITE">
 | |
|                 Require Team Invitations
 | |
|               </div>
 | |
|               <div class="help-text">
 | |
|                  If enabled, when adding a new user to a team, they will receive an invitation to join the team, with the option to decline.
 | |
|                  Otherwise, users will be immediately part of a team when added by a team administrator.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /Access settings -->
 | |
| 
 | |
|     <!-- Build Support -->
 | |
|     <div class="co-panel">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fa fa-tasks"></i> Dockerfile Build Support
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|            If enabled, users can submit Dockerfiles to be built and pushed by <span class="registry-name"></span>.
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_BUILD_SUPPORT">
 | |
|           Enable Dockerfile Build
 | |
|         </div>
 | |
| 
 | |
|         <div ng-if="config.FEATURE_BUILD_SUPPORT" style="margin-top: 10px">
 | |
|           <strong>Note: Build workers are required for this feature.</strong>
 | |
|            See <a href="https://coreos.com/docs/enterprise-registry/build-support/" ng-safenewtab>Adding Build Workers</a> for instructions on how to setup build workers.
 | |
|         </div>
 | |
|       </div>
 | |
|     </div> <!-- /Build Support -->
 | |
| 
 | |
|     <!-- GitHub Trigger -->
 | |
|     <div class="co-panel" ng-if="config.FEATURE_BUILD_SUPPORT" style="margin-top: 20px;">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fab fa-github"></i> GitHub (Enterprise) Build Triggers
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>
 | |
|             If enabled, users can setup GitHub or GitHub Enterprise triggers to invoke Registry builds.
 | |
|           </p>
 | |
|           <p>
 | |
|             <strong>Note:</strong> A registered GitHub (Enterprise) OAuth application (<strong>separate from GitHub Authentication</strong>) is required.
 | |
|             View instructions on how to
 | |
|             <a href="https://coreos.com/docs/enterprise-registry/github-app/" ng-safenewtab>
 | |
|               Create an OAuth Application in GitHub
 | |
|             </a>
 | |
|           </p>
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_GITHUB_BUILD">
 | |
|           Enable GitHub Triggers
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_GITHUB_BUILD">
 | |
|           <tr>
 | |
|             <td>GitHub:</td>
 | |
|             <td>
 | |
|               <select class="form-control" ng-model="mapped.GITHUB_TRIGGER_KIND">
 | |
|                 <option value="hosted">GitHub.com</option>
 | |
|                 <option value="enterprise">GitHub Enterprise</option>
 | |
|               </select>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr ng-if="mapped.GITHUB_TRIGGER_KIND == 'enterprise'">
 | |
|             <td>GitHub Endpoint:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field"
 | |
|                     binding="config.GITHUB_TRIGGER_CONFIG.GITHUB_ENDPOINT"
 | |
|                     placeholder="https://my.githubserver"
 | |
|                     pattern="{{ GITHOST_REGEX }}">
 | |
|               </span>
 | |
|               <div class="help-text">
 | |
|                 The GitHub Enterprise endpoint. Must start with http:// or https://.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>OAuth Client ID:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.GITHUB_TRIGGER_CONFIG.CLIENT_ID">
 | |
|               </span>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>OAuth Client Secret:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.GITHUB_TRIGGER_CONFIG.CLIENT_SECRET">
 | |
|               </span>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /GitHub Trigger -->
 | |
| 
 | |
|     <!-- BitBucket Trigger -->
 | |
|     <div class="co-panel" ng-if="config.FEATURE_BUILD_SUPPORT" style="margin-top: 20px;">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fab fa-bitbucket"></i> BitBucket Build Triggers
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>
 | |
|             If enabled, users can setup BitBucket triggers to invoke Registry builds.
 | |
|           </p>
 | |
|           <p>
 | |
|             <strong>Note:</strong> A registered BitBucket OAuth application is required.
 | |
|             View instructions on how to
 | |
|             <a href="https://coreos.com/docs/enterprise-registry/bitbucket-app/" ng-safenewtab>
 | |
|               Create an OAuth Application in BitBucket
 | |
|             </a>
 | |
|           </p>
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_BITBUCKET_BUILD">
 | |
|           Enable BitBucket Triggers
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_BITBUCKET_BUILD">
 | |
|           <tr>
 | |
|             <td>OAuth Consumer Key:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.BITBUCKET_TRIGGER_CONFIG.CONSUMER_KEY">
 | |
|               </span>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>OAuth Consumer Secret:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.BITBUCKET_TRIGGER_CONFIG.CONSUMER_SECRET">
 | |
|               </span>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /BitBucket Trigger -->
 | |
| 
 | |
|     <!-- GitLab Trigger -->
 | |
|     <div class="co-panel" ng-if="config.FEATURE_BUILD_SUPPORT" style="margin-top: 20px;">
 | |
|       <div class="co-panel-heading">
 | |
|         <i class="fab fa-gitlab"></i> GitLab Build Triggers
 | |
|       </div>
 | |
|       <div class="co-panel-body">
 | |
|         <div class="description">
 | |
|           <p>
 | |
|             If enabled, users can setup GitLab triggers to invoke Registry builds.
 | |
|           </p>
 | |
|           <p>
 | |
|             <strong>Note:</strong> A registered GitLab OAuth application is required.
 | |
|             Visit the
 | |
|             <a href="{{ config.GITLAB_TRIGGER_CONFIG.GITLAB_ENDPOINT || 'https://gitlab.com' }}/profile/applications" ng-safenewtab>
 | |
|               GitLab applications admin panel
 | |
|             </a>
 | |
|             to create a new application.
 | |
|           </p>
 | |
|           <p>The callback URL to use is:  
 | |
|               <code>{{ config.PREFERRED_URL_SCHEME || 'http' }}://{{ config.SERVER_HOSTNAME || 'localhost' }}/oauth2/gitlab/callback/trigger</code>
 | |
|           </p>
 | |
|         </div>
 | |
| 
 | |
|         <div class="config-bool-field" binding="config.FEATURE_GITLAB_BUILD">
 | |
|           Enable GitLab Triggers
 | |
|         </div>
 | |
| 
 | |
|         <table class="config-table" ng-if="config.FEATURE_GITLAB_BUILD">
 | |
|           <tr>
 | |
|             <td>GitLab:</td>
 | |
|             <td>
 | |
|               <select class="form-control" ng-model="mapped.GITLAB_TRIGGER_KIND">
 | |
|                 <option value="hosted">GitLab.com</option>
 | |
|                 <option value="enterprise">GitLab CE/EE</option>
 | |
|               </select>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr ng-if="mapped.GITLAB_TRIGGER_KIND == 'enterprise'">
 | |
|             <td>GitLab Endpoint:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field"
 | |
|                     binding="config.GITLAB_TRIGGER_CONFIG.GITLAB_ENDPOINT"
 | |
|                     placeholder="https://my.gitlabserver"
 | |
|                     pattern="{{ GITHOST_REGEX }}">
 | |
|               </span>
 | |
|               <div class="help-text">
 | |
|                 The GitLab Enterprise endpoint. Must start with http:// or https://.
 | |
|               </div>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Application Id:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.GITLAB_TRIGGER_CONFIG.CLIENT_ID">
 | |
|               </span>
 | |
|             </td>
 | |
|           </tr>
 | |
|           <tr>
 | |
|             <td>Secret:</td>
 | |
|             <td>
 | |
|               <span class="config-string-field" binding="config.GITLAB_TRIGGER_CONFIG.CLIENT_SECRET">
 | |
|               </span>
 | |
|             </td>
 | |
|           </tr>
 | |
|         </table>
 | |
|       </div>
 | |
|     </div> <!-- /GitLab Trigger -->
 | |
| 
 | |
|     </div>
 | |
|     </form>
 | |
| 
 | |
|     <!-- Save Bar -->
 | |
|     <div class="cor-floating-bottom-bar">
 | |
|       <button class="btn" ng-class="mapped.$hasChanges ? 'btn-primary' : 'btn-success'"
 | |
|               ng-click="checkValidateAndSave()" ng-show="configform.$valid">
 | |
|         <i class="fa fa-lg" ng-class="mapped.$hasChanges ? 'fa-dot-circle-o' : 'fa-check-circle'"></i>
 | |
|         <span ng-if="mapped.$hasChanges">Save Configuration Changes</span>
 | |
|         <span ng-if="!mapped.$hasChanges">Configuration Saved</span>
 | |
|       </button>
 | |
|       <button class="btn btn-warning" ng-click="checkValidateAndSave()" ng-show="!configform.$valid"
 | |
|               ng-click="checkValidateAndSave()">
 | |
|         <i class="fa fa-lg fa-sort"></i>
 | |
|         <span ng-if="configform.$error['required'].length">
 | |
|           {{ configform.$error['required'].length }} configuration field<span ng-show="configform.$error['required'].length != 1">s</span> remaining
 | |
|         </span>
 | |
|         <span ng-if="!configform.$error['required'].length">
 | |
|           Invalid configuration field
 | |
|         </span>
 | |
|       </button>
 | |
|     </div>
 | |
| 
 | |
|     <!-- Modal message dialog -->
 | |
|     <div class="modal co-dialog fade initial-setup-modal" id="validateAndSaveModal">
 | |
|       <div class="modal-dialog">
 | |
|         <div class="modal-content">
 | |
|           <div class="modal-header">
 | |
|             <span class="cor-step-bar">
 | |
|               <span class="cor-step active" title="Configure Database" text="1"></span>
 | |
|               <span class="cor-step active" title="Setup Database" icon="database"></span>
 | |
|               <span class="cor-step active" title="Create Superuser" text="2"></span>
 | |
|               <span class="cor-step active" title="Configure Registry" text="3"></span>
 | |
|               <span class="cor-step active" title="Validate Configuration" text="4"></span>
 | |
|               <span class="cor-step" title="Setup Complete" icon="download"></span>
 | |
|             </span>
 | |
|           <h4 class="modal-title">
 | |
|               Checking your settings
 | |
|           </h4>
 | |
|           </div>
 | |
|           <div class="modal-body">
 | |
|             <div class="service-verification">
 | |
|               <div class="service-verification-row" ng-repeat="serviceInfo in validating">
 | |
|                 <span class="quay-spinner" ng-show="serviceInfo.status == 'validating'"></span>
 | |
|                 <i class="fa fa-lg fa-check-circle" ng-show="serviceInfo.status == 'success'"></i>
 | |
|                 <i class="fa fa-lg fa-warning" ng-show="serviceInfo.status == 'error'"></i>
 | |
|                 <span class="service-title">{{ serviceInfo.service.title }}</span>
 | |
| 
 | |
|                 <div class="service-verification-error" ng-show="serviceInfo.status == 'error'">{{ serviceInfo.errorMessage }}</div>
 | |
|               </div>
 | |
|             </div>
 | |
|           </div>
 | |
| 
 | |
|           <!-- Footer: Saving configuration -->
 | |
|           <div class="modal-footer working" ng-show="savingConfiguration">
 | |
|             <span class="cor-loader-inline"></span> Saving Configuration...
 | |
|           </div>
 | |
| 
 | |
|           <!-- Footer: Validating -->
 | |
|           <div class="modal-footer working"
 | |
|                ng-show="!savingConfiguration && validationStatus(validating) == 'validating'">
 | |
|             <span class="cor-loader-inline"></span> Validating settings...
 | |
| 
 | |
|             <button class="btn btn-default" ng-click="cancelValidation()">
 | |
|               Stop Validating
 | |
|             </button>
 | |
|           </div>
 | |
| 
 | |
|           <!-- Footer: Valid Config -->
 | |
|           <div class="modal-footer"
 | |
|                ng-show="!savingConfiguration && validationStatus(validating) == 'success'">
 | |
|             <span class="left-align">
 | |
|               <i class="fa fa-check"></i>
 | |
|               Configuration Validated
 | |
|             </span>
 | |
| 
 | |
|             <button class="btn btn-primary"
 | |
|                     ng-click="saveConfiguration()"
 | |
|                     ng-disabled="savingConfiguration">
 | |
|                     Next
 | |
|             </button>
 | |
|           </div>
 | |
| 
 | |
|           <!-- Footer: Invalid Config -->
 | |
|           <div class="modal-footer"
 | |
|                ng-show="!savingConfiguration && validationStatus(validating) == 'failed'">
 | |
|             <span class="left-align">
 | |
|               <i class="fa fa-warning"></i>
 | |
|               Problem Detected
 | |
|             </span>
 | |
| 
 | |
|             <button class="btn btn-default" data-dismiss="modal">
 | |
|               Continue Editing
 | |
|             </button>
 | |
|           </div>
 | |
| 
 | |
|         </div><!-- /.modal-content -->
 | |
|       </div><!-- /.modal-dialog -->
 | |
|     </div><!-- /.modal -->
 | |
| 
 | |
|   </div>
 | |
| </div>
 |