Merge commit 'd12d3b2cecbfb5a85bf219fa146a02b523dd6352'

* commit 'd12d3b2cecbfb5a85bf219fa146a02b523dd6352':
  systemctl removed ".service"
  comments about Certbot renewal fixes #79
  nginx -> NGINX
  style fixes
  refactored command with steps
  site group, preset group
  moved github to header
  moved loader to header
  build:scss:watch
  application/rss+xml fix fixes #89
  node-sass
  site selector refactor

# Conflicts:
#	package.json
pull/85/head
Bálint Szekeres 2019-05-19 18:20:18 +02:00
commit 54d66e9e45
14 changed files with 1499 additions and 1115 deletions

948
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,14 +22,14 @@
"angular-tooltips": "^1.2.2", "angular-tooltips": "^1.2.2",
"autoprefixer": "^8.6.4", "autoprefixer": "^8.6.4",
"bootstrap": "^4.2.1", "bootstrap": "^4.2.1",
"eslint": "^5.9.0", "eslint": "^5.16.0",
"highlight.js": "^9.12.0", "highlight.js": "^9.12.0",
"js-base64": "^2.5.1", "js-base64": "^2.5.1",
"node-sass": "^4.11.0", "node-sass": "^4.12.0",
"postcss-cli": "^5.0.1" "postcss-cli": "^5.0.1"
}, },
"devDependencies": { "devDependencies": {
"cypress": "^3.1.2", "cypress": "^3.2.0",
"http-server": "^0.11.1", "http-server": "^0.11.1",
"start-server-and-test": "^1.5.0" "start-server-and-test": "^1.5.0"
}, },
@ -39,6 +39,7 @@
"build:prod": "npm run build:scss:prod && npm run autoprefixer", "build:prod": "npm run build:scss:prod && npm run autoprefixer",
"build:scss": "node-sass --source-map=public/assets/css/app.min.css.map resources/scss/app.scss public/assets/css/app.min.css", "build:scss": "node-sass --source-map=public/assets/css/app.min.css.map resources/scss/app.scss public/assets/css/app.min.css",
"build:scss:prod": "node-sass --output-style=compressed resources/scss/app.scss public/assets/css/app.min.css", "build:scss:prod": "node-sass --output-style=compressed resources/scss/app.scss public/assets/css/app.min.css",
"build:scss:watch": "npm run build:scss -- --watch",
"autoprefixer": "postcss public/assets/css/app.min.css --use autoprefixer --no-map --replace --verbose", "autoprefixer": "postcss public/assets/css/app.min.css --use autoprefixer --no-map --replace --verbose",
"lint": "eslint public/assets/js/app.js", "lint": "eslint public/assets/js/app.js",
"lint:fix": "npm run lint -- --fix", "lint:fix": "npm run lint -- --fix",

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check-circle"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>

After

Width:  |  Height:  |  Size: 328 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-download-cloud"><polyline points="8 17 12 21 16 17"></polyline><line x1="12" y1="12" x2="12" y2="21"></line><path d="M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29"></path></svg>

After

Width:  |  Height:  |  Size: 387 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-lock"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>

After

Width:  |  Height:  |  Size: 321 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-terminal"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>

After

Width:  |  Height:  |  Size: 310 B

View File

@ -205,7 +205,7 @@
} }
for (var i in siteTabs) { for (var i in siteTabs) {
$scope.siteChanges[$scope.site][siteTabs[i]] = $window.document.querySelectorAll('section.tabs .tab-content.site-tab-content .tab-' + siteTabs[i] + ' .form-group:not(.disabled) .input-changed').length; $scope.siteChanges[$scope.site][siteTabs[i]] = $window.document.querySelectorAll('section.tabs .tab-content.site-content .tab-' + siteTabs[i] + ' .form-group:not(.disabled) .input-changed').length;
} }
for (var j in commonTabs) { for (var j in commonTabs) {
@ -385,7 +385,9 @@
$scope.clipboardCopy = undefined; $scope.clipboardCopy = undefined;
$scope.gzipTypes = 'text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml'; $scope.activeStep = 'download';
$scope.gzipTypes = 'text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml';
$scope.extensions = { $scope.extensions = {
assets: 'css(\\.map)?|js(\\.map)?', assets: 'css(\\.map)?|js(\\.map)?',
@ -521,6 +523,10 @@
}); });
}; };
$scope.setActiveStep = function(step) {
$scope.activeStep = step;
};
$scope.getSiteChanges = function(site) { $scope.getSiteChanges = function(site) {
if ($scope.siteChanges[site] === undefined) { if ($scope.siteChanges[site] === undefined) {
return undefined; return undefined;
@ -1027,6 +1033,7 @@
// www // www
$scope.data.sites[site].domain = $scope.data.sites[site].domain.replace(/^https?:\/\//, ''); $scope.data.sites[site].domain = $scope.data.sites[site].domain.replace(/^https?:\/\//, '');
$scope.data.sites[site].domain = $scope.data.sites[site].domain.replace(/\/.*$/, ''); $scope.data.sites[site].domain = $scope.data.sites[site].domain.replace(/\/.*$/, '');
$scope.data.sites[site].domain = $scope.data.sites[site].domain.replace(' ', '');
if ($scope.data.sites[site].domain.match(/^www\./)) { if ($scope.data.sites[site].domain.match(/^www\./)) {
$scope.data.sites[site].domain = $scope.data.sites[site].domain.replace(/^www./, ''); $scope.data.sites[site].domain = $scope.data.sites[site].domain.replace(/^www./, '');

View File

@ -17,10 +17,37 @@
</head> </head>
<body ng-app="NginxConfigIoApp" ng-controller="NginxConfigIoController"> <body ng-app="NginxConfigIoApp" ng-controller="NginxConfigIoController">
<header> <header>
<div class="container-fluid"> <div class="container">
<div class="loader" ng-if="!masonryInit">
<div class="spinner">
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
</div>
<img src="assets/img/logo-light.svg" class="logo" alt="nginxconfig.io"> <img src="assets/img/logo-light.svg" class="logo" alt="nginxconfig.io">
<div class="github">
<iframe class="github-star" src="https://ghbtns.com/github-btn.html?user=valentinxxx&repo=nginxconfig.io&type=star&count=true&size=large"></iframe>
<div class="github-link">
<ng-include src="'/assets/img/brands/github.svg'"></ng-include> <a href="https://github.com/valentinxxx/nginxconfig.io" target="_blank"><small>valentinxxx /</small> <strong>nginxconfig.io</strong></a>
</div>
</div>
<div class="sites">
<div class="title">Sites:</div>
<div class="group">
<button class="btn btn-sm btn-outline-light" ng-repeat="(key, value) in data.sites" ng-click="setSite(key)" ng-class="{ 'active': site === key }" ng-cloak>
{{ getDomain(key) }}<small ng-cloak>({{ getSiteChanges(key) !== undefined ? getSiteChanges(key) : '?' }})</small>
<span class="close" ng-if="key > 0" ng-click="removeSite(key)">&times;</span>
</button>
<button class="btn btn-sm btn-outline-light" ng-click="addSite()"> Add site</button>
</div>
</div>
<div class="presets"> <div class="presets">
<div class="title">Presets:</div>
<div class="group">
<button <button
type="button" type="button"
class="btn btn-sm btn-outline-light" class="btn btn-sm btn-outline-light"
@ -95,30 +122,13 @@
><span ng-include="'assets/img/brands/magento.svg'"></span> Magento</button> ><span ng-include="'assets/img/brands/magento.svg'"></span> Magento</button>
</div> </div>
</div> </div>
</div>
</header> </header>
<section class="tabs"> <section class="tabs">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
<div class="sites"> <div class="sites">
<ul class="nav nav-tabs nav-site" role="tablist">
<li class="nav-item disabled">
<a class="nav-link">Sites:</a>
</li>
<li class="nav-item" ng-repeat="(key, value) in data.sites">
<a class="nav-link" ng-click="setSite(key)" ng-class="{ 'active': site === key, 'changed': getSiteChanges(key) !== 0 }" ng-cloak>
{{ getDomain(key) }}<small ng-cloak>({{ getSiteChanges(key) !== undefined ? getSiteChanges(key) : '?' }})</small>
<button type="button" class="close" ng-if="key > 0" ng-click="removeSite(key)">
<span>&times;</span>
</button>
</a>
</li>
<li class="nav-item">
<a class="nav-link text-muted small" ng-click="addSite()">﹢ Add site</a>
</li>
</ul>
<div class="tab-content site-content">
<div class="tab-pane active">
<ul class="nav nav-tabs nav-site-tab" role="tablist"> <ul class="nav nav-tabs nav-site-tab" role="tablist">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" ng-click="setTabSite('server')" ng-class="{ 'active': tab_site === 'server', 'changed': getSiteTabChanges('server') }">Server<small ng-cloak>({{ getSiteTabChanges('server') }})</small></a> <a class="nav-link" ng-click="setTabSite('server')" ng-class="{ 'active': tab_site === 'server', 'changed': getSiteTabChanges('server') }">Server<small ng-cloak>({{ getSiteTabChanges('server') }})</small></a>
@ -142,7 +152,7 @@
<a class="nav-link" ng-click="setTabSite('logging')" ng-class="{ 'active': tab_site === 'logging', 'changed': getSiteTabChanges('logging') }">Logging<small ng-cloak>({{ getSiteTabChanges('logging') }})</small></a> <a class="nav-link" ng-click="setTabSite('logging')" ng-class="{ 'active': tab_site === 'logging', 'changed': getSiteTabChanges('logging') }">Logging<small ng-cloak>({{ getSiteTabChanges('logging') }})</small></a>
</li> </li>
</ul> </ul>
<div class="tab-content site-tab-content"> <div class="tab-content site-content">
<div class="tab-pane tab-server" ng-class="{ 'active': tab_site === 'server' }"> <div class="tab-pane tab-server" ng-class="{ 'active': tab_site === 'server' }">
<div class="row mb-2"> <div class="row mb-2">
<div class="col-sm-4"> <div class="col-sm-4">
@ -557,13 +567,10 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
<div class="common"> <div class="common">
<ul class="nav nav-tabs nav-common" role="tablist"> <ul class="nav nav-tabs nav-common" role="tablist">
<li class="nav-item disabled"> <li class="nav-item disabled">
<a class="nav-link">Common:</a> <a class="nav-link">Global:</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" ng-click="setTabCommon('https')" ng-class="{ 'active': tab_common === 'https', 'changed': commonChanges['https'] }">HTTPS<small ng-cloak>({{ commonChanges['https'] }})</small></a> <a class="nav-link" ng-click="setTabCommon('https')" ng-class="{ 'active': tab_common === 'https', 'changed': commonChanges['https'] }">HTTPS<small ng-cloak>({{ commonChanges['https'] }})</small></a>
@ -584,7 +591,7 @@
<a class="nav-link" ng-click="setTabCommon('logging')" ng-class="{ 'active': tab_common === 'logging', 'changed': commonChanges['logging'] }">Logging<small ng-cloak>({{ commonChanges['logging'] }})</small></a> <a class="nav-link" ng-click="setTabCommon('logging')" ng-class="{ 'active': tab_common === 'logging', 'changed': commonChanges['logging'] }">Logging<small ng-cloak>({{ commonChanges['logging'] }})</small></a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" ng-click="setTabCommon('nginx')" ng-class="{ 'active': tab_common === 'nginx', 'changed': commonChanges['nginx'] }">nginx<small ng-cloak>({{ commonChanges['nginx'] }})</small></a> <a class="nav-link" ng-click="setTabCommon('nginx')" ng-class="{ 'active': tab_common === 'nginx', 'changed': commonChanges['nginx'] }">NGINX<small ng-cloak>({{ commonChanges['nginx'] }})</small></a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-muted" ng-click="setTabCommon('tools')" ng-class="{ 'active': tab_common === 'tools', 'changed': commonChanges['tools'] }">Tools<small ng-cloak>({{ commonChanges['tools'] }})</small></a> <a class="nav-link text-muted" ng-click="setTabCommon('tools')" ng-class="{ 'active': tab_common === 'tools', 'changed': commonChanges['tools'] }">Tools<small ng-cloak>({{ commonChanges['tools'] }})</small></a>
@ -960,10 +967,6 @@
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<aside class="sidebar"> <aside class="sidebar">
<iframe class="github-star" src="https://ghbtns.com/github-btn.html?user=valentinxxx&repo=nginxconfig.io&type=star&count=true&size=large"></iframe>
<div class="github-link">
<img src="assets/img/brands/github.svg" alt="GitHub"> <a href="https://github.com/valentinxxx/nginxconfig.io" target="_blank"><small>valentinxxx /</small> <strong>nginxconfig.io</strong></a>
</div>
<div class="adsbygoogle-container"> <div class="adsbygoogle-container">
<div class="note">▾ advertisement ▾</div> <div class="note">▾ advertisement ▾</div>
<ins class="adsbygoogle" <ins class="adsbygoogle"
@ -981,21 +984,53 @@
</div> </div>
</div> </div>
</section> </section>
<section class="loader" ng-if="!masonryInit"> <section class="steps">
<div class="spinner"> <div class="container">
<div class="double-bounce1"></div> <div class="row">
<div class="double-bounce2"></div> <div class="col-xl-10 offset-xl-1">
<ol ng-attr-data-active-step="{{ activeStep }}">
<li
class="download"
ng-mouseenter="setActiveStep('download')">
<div class="circle" ng-include="'/assets/img/download-cloud.svg'"></div>
<span class="counter"></span>Download
</li>
<li
class="ssl"
ng-if="isHTTPS() && (isSSLDHRequired() || isCertLetsEncrypt())"
ng-mouseenter="setActiveStep('ssl')">
<div class="circle" ng-include="'/assets/img/lock.svg'"></div>
<span class="counter"></span>SSL init
</li>
<li
class="certbot"
ng-if="isHTTPS() && isCertLetsEncrypt()"
ng-mouseenter="setActiveStep('certbot')">
<div class="circle" ng-include="'/assets/img/terminal.svg'"></div>
<span class="counter"></span>Certbot
</li>
<li
class="live"
ng-mouseenter="setActiveStep('live')">
<div class="circle" ng-include="'/assets/img/check-circle.svg'"></div>
<span class="counter"></span>Go Live!
</li>
</ol>
</div>
</div>
</div> </div>
</section> </section>
<main ng-class="{ 'active': masonryInit }"> <main ng-class="{ 'active': masonryInit }">
<div class="container"> <div class="container">
<div class="row grid"> <div class="col-xl-10 offset-xl-1">
<div class="grid-sizer col-xl-6"></div> <div class="commands" ng-cloak>
<div ng-if="isSymlink() || (isHTTPS() && (isCertLetsEncrypt() || isSSLDHRequired()))" class="grid-item col-xl-10 offset-xl-1" ng-cloak>
<div class="commands">
<pre><code class="hljs bash" ng-include="'templates/commands.html?v=COMMIT_HASH'"></code></pre> <pre><code class="hljs bash" ng-include="'templates/commands.html?v=COMMIT_HASH'"></code></pre>
</div> </div>
</div> </div>
<div class="row grid">
<div class="grid-sizer col-xl-6"></div>
<div class="grid-item col-xl-12 mb-3 text-center" ng-cloak> <div class="grid-item col-xl-12 mb-3 text-center" ng-cloak>
<button class="btn btn-primary btn-sm btn-download" ng-click="downloadZip()"><img src="assets/img/download.svg" alt="Download"> Generated config <small>(.zip)</small></button> <button class="btn btn-primary btn-sm btn-download" ng-click="downloadZip()"><img src="assets/img/download.svg" alt="Download"> Generated config <small>(.zip)</small></button>
<button tooltips tooltip-template="Copied!" tooltip-show-trigger="click" class="btn btn-success btn-sm btn-download btn-base64" ng-click="downloadBase64()"><img src="assets/img/download.svg" alt="Download"> Copy Base64 <small>(inline)</small></button> <button tooltips tooltip-template="Copied!" tooltip-show-trigger="click" class="btn btn-success btn-sm btn-download btn-base64" ng-click="downloadBase64()"><img src="assets/img/download.svg" alt="Download"> Copy Base64 <small>(inline)</small></button>

View File

@ -1,65 +1,70 @@
<!-- ✔ symlink --><span ng-if="isSymlink()"><!-- <span class="step" ng-if="activeStep === 'download'"><!--
--><span class="hljs-comment"># <strong>Virtual host</strong>: create symbolic link{{ getDomains().length > 1 ? 's' : '' }}</span> step: download
<span class="hljs-section">ln</span> <span class="hljs-attribute">-s</span> <span ng-repeat="(_site, _domain) in getDomains() track by $index">/etc/nginx/sites-available/{{ _domain }}.conf </span>/etc/nginx/sites-enabled</span><!--
--><span class="hljs-comment"><span class="counter">.</span> Download generated config:</span> <strong><a href="#" ng-click="downloadZip()">nginxconfig.io-{{ getDomains().join(',') }}.zip</a></strong>
<span class="hljs-comment"><span class="counter">.</span> Upload to server's <strong>/etc/nginx/</strong> directory</span>
<span class="hljs-comment"><span class="counter">.</span> Backup current configuration:</span>
<span class="hljs-section">tar</span> <span class="hljs-attribute">-czvf</span> nginx_$(date +'%F_%H-%M-%S').tar.gz nginx.conf sites-available/ sites-enabled/ nginxconfig.io/
<span class="hljs-comment"><span class="counter">.</span> Unzip the uploaded archive:</span>
<span class="hljs-section">cd</span> /etc/nginx
<span class="hljs-section">unzip</span> <span class="hljs-attribute">-o</span> nginxconfig.io-{{ getDomains().join(',') }}.zip <span class="hljs-comment">(you probably need to install <strong>unzip</strong>:</span> <span class="hljs-section"></span><strong>sudo</strong> <span class="hljs-section">apt-get</span> <span class="hljs-attribute">install</span> unzip<span class="hljs-comment">)</span></span><!--
✔ symlink || ✔ HTTPS --><span ng-if="isSymlink() && (isSSLDHRequired() || hasCertLetsEncrypt())">
--><span class="step" ng-if="activeStep === 'ssl'"><!--
step: ssl
--><!--
✔ SSL DH required --><span ng-if="isSSLDHRequired()"><span class="hljs-comment"><span class="counter">.</span> Generate Diffie-Hellman keys:</span>
<span class="hljs-section">openssl</span> <span class="hljs-attribute">dhparam -dsaparam</span> <span class="hljs-attribute">-out</span> /etc/nginx/dhparam.pem <span class="hljs-number">{{ isSSLProfileLegacy() ? 1024 : 2048 }}</span>
</span><!-- </span><!--
✔ Let's Encrypt
✔ SSL DH required --><span ng-if="isSSLDHRequired()"><!-- --><span ng-if="hasCertLetsEncrypt()"><span class="hljs-comment"><span class="counter">.</span> Create a common ACME-challenge directory (for Let's Encrypt):</span>
<span class="hljs-section">mkdir</span> <span class="hljs-attribute">-p</span> /var/www/_letsencrypt
--><span class="hljs-comment"># <strong>HTTPS</strong>: create Diffie-Hellman keys</span> <span class="hljs-section">chown</span> <span class="hljs-attribute">{{ data.user }}</span> /var/www/_letsencrypt</span></span><!--
<span class="hljs-section">openssl dhparam</span> <span class="hljs-attribute">-dsaparam</span> <span class="hljs-attribute">-out</span> /etc/nginx/dhparam.pem <span class="hljs-number">{{ isSSLProfileLegacy() ? 1024 : 2048 }}</span><!--
--><span ng-if="hasCertLetsEncrypt()">
</span></span><!--
✔ Let's Encrypt --><span ng-if="hasCertLetsEncrypt()"><!--
--><span class="hljs-comment"># <strong>HTTPS - certbot</strong> (before first run): create ACME-challenge common directory</span>
<span class="hljs-section">mkdir</span> <span class="hljs-attribute">-p</span> /var/www/_letsencrypt && <span class="hljs-section">chown</span> <span class="hljs-attribute">{{ data.user }}</span> /var/www/_letsencrypt
<!--
--> --><span class="step" ng-if="activeStep === 'certbot'"><!--
<span class="hljs-comment"># <strong>HTTPS - certbot</strong> (before first run): disable SSL directives</span>
<span class="hljs-section">sed</span> <!-- step: certbot
--><span class="hljs-attribute">-i</span> <!--
--><span class="hljs-attribute">-r</span> <!-- --><span class="hljs-comment"><span class="counter">.</span> Comment out SSL related directives in configuration:</span>
-->'s/(listen .*443)/\1;#/g; s/(ssl_(certificate|certificate_key|trusted_certificate) )/#;#\1/g'<span ng-if="isUnified()"><!-- <span class="hljs-section">sed</span> <span class="hljs-attribute">-i -r</span> 's/(listen .*443)/\1;#/g; s/(ssl_(certificate|certificate_key|trusted_certificate) )/#;#\1/g'<span ng-if="isUnified()"><!--
--> /etc/nginx/nginx.conf</span><span ng-if="isModularized()"><span ng-repeat="(_site, _domain) in getDomains() track by $index" ng-if="isCertLetsEncrypt(_site)"><!-- --> /etc/nginx/nginx.conf</span><span ng-if="isModularized()"><span ng-repeat="(_site, _domain) in getDomains() track by $index" ng-if="isCertLetsEncrypt(_site)"><!--
--> /etc/nginx/sites-{{ isSymlink() ? 'available' : 'enabled' }}/{{ _domain }}.conf</span></span> --> /etc/nginx/sites-{{ isSymlink() ? 'available' : 'enabled' }}/{{ _domain }}.conf</span></span>
<!-- <span class="hljs-comment"><span class="counter">.</span> Configure <strong>Certbot</strong> to reload <strong>NGINX</strong> on success:</span>
<span class="hljs-section">echo</span> <span class="hljs-attribute">-e</span> '#!/bin/bash\nnginx -t && systemctl reload nginx' | <strong>sudo</strong> <span class="hljs-section">tee</span> /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh
<strong>sudo</strong> <span class="hljs-section">chmod</span> <span class="hljs-attribute">a+x</span> /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh
<span class="hljs-comment"><span class="counter">.</span> Obtain certificate{{ getDomains().length > 1 ? 's' : '' }}:</span><!--
-->
<span class="hljs-comment"># <strong>HTTPS - certbot</strong>: obtain certificates</span><!--
--><span ng-repeat="(_site, _domain) in getDomains() track by $index" ng-if="isCertLetsEncrypt(_site)"> --><span ng-repeat="(_site, _domain) in getDomains() track by $index" ng-if="isCertLetsEncrypt(_site)">
<span class="hljs-section">certbot certonly</span> <!-- <span class="hljs-section">certbot</span> <!--
--><span class="hljs-attribute">certonly</span> <!--
--><span class="hljs-attribute">--webroot</span> <!-- --><span class="hljs-attribute">--webroot</span> <!--
--><span ng-if="isNonWWW(_site) || isRedirect(_site)"><span class="hljs-attribute" tooltips tooltip-template="--domain">-d</span> {{ _domain }} </span><!-- --><span ng-if="isNonWWW(_site) || isRedirect(_site)"><span class="hljs-attribute" tooltips tooltip-template="--domain" tooltip-side="top">-d</span> {{ _domain }} </span><!--
--><span ng-if="isWWW(_site) || isRedirect(_site)"><span class="hljs-attribute" tooltips tooltip-template="--domain">-d</span> www.{{ _domain }} </span><!-- --><span ng-if="isWWW(_site) || isRedirect(_site)"><span class="hljs-attribute" tooltips tooltip-template="--domain" tooltip-side="top">-d</span> www.{{ _domain }} </span><!--
--><span ng-if="isCDN(_site)"><span class="hljs-attribute" tooltips tooltip-template="--domain">-d</span> cdn.{{ _domain }} </span><!-- --><span ng-if="isCDN(_site)"><span class="hljs-attribute" tooltips tooltip-template="--domain" tooltip-side="top">-d</span> cdn.{{ _domain }} </span><!--
--><span class="hljs-attribute">--email</span> {{ data.sites[_site].email ? data.sites[_site].email : 'info@' + _domain }} <!-- --><span class="hljs-attribute">--email</span> {{ data.sites[_site].email ? data.sites[_site].email : 'info@' + _domain }} <!--
--><span class="hljs-attribute" tooltips tooltip-template="--webroot-path">-w</span> /var/www/_letsencrypt <!-- --><span class="hljs-attribute" tooltips tooltip-template="--webroot-path" tooltip-side="top">-w</span> /var/www/_letsencrypt <!--
--><span class="hljs-attribute" tooltips tooltip-template="--non-interactive">-n</span> <!-- --><span class="hljs-attribute" tooltips tooltip-template="--non-interactive" tooltip-side="top">-n</span> <!--
--><span class="hljs-attribute">--agree-tos</span> <!-- --><span class="hljs-attribute">--agree-tos</span> <!--
--><span class="hljs-attribute">--force-renewal</span></span> --><span class="hljs-attribute">--force-renewal</span></span>
<!-- <span class="hljs-comment"><span class="counter">.</span> Uncomment SSL related directives in configuration:</span>
<span class="hljs-section">sed</span> <span class="hljs-attribute">-i -r</span> 's/#?;#//g'<span ng-if="isUnified()"><!--
-->
<span class="hljs-comment"># <strong>HTTPS - certbot</strong> (after first run): enable SSL directives</span>
<span class="hljs-section">sed</span> <!--
--><span class="hljs-attribute">-i</span> <!--
--><span class="hljs-attribute">-r</span> <!--
-->'s/#?;#//g'<span ng-if="isUnified()"><!--
--> /etc/nginx/nginx.conf</span><span ng-if="isModularized()"><span ng-repeat="(_site, _domain) in getDomains() track by $index" ng-if="isCertLetsEncrypt(_site)"><!-- --> /etc/nginx/nginx.conf</span><span ng-if="isModularized()"><span ng-repeat="(_site, _domain) in getDomains() track by $index" ng-if="isCertLetsEncrypt(_site)"><!--
--> /etc/nginx/sites-{{ isSymlink() ? 'available' : 'enabled' }}/{{ _domain }}.conf</span></span></span> --> /etc/nginx/sites-{{ isSymlink() ? 'available' : 'enabled' }}/{{ _domain }}.conf</span></span>
<span class="hljs-comment"><span class="counter">.</span> Schedule renewing:
You're ready, Certbot will renew any certificates that expire in less than 30 days</span></span><!--
--><span class="step" ng-if="activeStep === 'live'"><!--
step: live
--><span class="hljs-comment"><span class="counter">.</span> Reload <strong>NGINX</strong></span>
<strong>sudo</strong> <span class="hljs-section">nginx</span> <span class="hljs-attribute">-t</span> && <strong>sudo</strong> <span class="hljs-section">systemctl</span> <span class="hljs-attribute">reload</span> nginx</span>

View File

@ -1,22 +1,159 @@
@keyframes sk-bounce {
0%, 100% {
transform: scale(0.0);
} 50% {
transform: scale(1.0);
}
}
header { header {
background-color: #000; background-color: #000;
padding: 0.5rem 0 0.25rem; padding: 0.5rem 0;
text-align: center; text-align: center;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
color: #fff; color: #fff;
font-size: 2.2rem; font-size: 2.2rem;
.logo { .container {
height: 3rem; position: relative;
margin: 0.5rem 0 0.3rem;
} }
.loader {
position: absolute;
top: 5px;
left: 50%;
pointer-events: none;
margin-left: -230px;
.spinner {
width: 50px;
height: 50px;
position: relative;
.double-bounce1,
.double-bounce2 {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #999;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
animation: sk-bounce 2.0s infinite ease-in-out;
}
.double-bounce2 {
animation-delay: -1.0s;
}
}
}
.logo {
height: 3rem;
margin-bottom: 0.5rem;
}
.github {
@include media-breakpoint-up(lg) {
position: absolute;
right: 15px;
top: 10px;
}
.github-link {
text-align: center;
font-size: 1rem;
margin-bottom: 0.5rem;
a {
color: #fff;
}
small {
font-size: 90%;
}
svg {
height: 1.2rem;
vertical-align: -4px;
g {
fill: #fff;
}
}
}
.github-star {
width: 144px;
height: 30px;
display: block;
border: 0;
overflow: hidden;
margin: 0 auto 0.25rem;
@include media-breakpoint-up(lg) {
margin-left: auto;
}
}
}
.sites {
@include media-breakpoint-up(lg) {
margin-top: -1rem;
}
}
.sites,
.presets { .presets {
margin-bottom: 0.3rem; font-size: 0;
line-height: 1.8rem; text-align: center;
@include media-breakpoint-up(lg) {
text-align: left;
}
}
.sites .title,
.presets .title {
color: #eee;
font-size: 0.9rem;
line-height: 1.9rem;
font-style: italic;
vertical-align: top;
margin-right: 4px;
text-align: center;
@include media-breakpoint-up(lg) {
display: inline-block;
width: 60px;
}
}
.sites .group,
.presets .group {
@include media-breakpoint-up(lg) {
display: inline-block;
vertical-align: top;
}
}
.sites .group {
@include media-breakpoint-up(lg) {
width: calc(100% - 290px);
}
}
.presets .group {
@include media-breakpoint-up(lg) {
width: calc(100% - 64px);
}
}
.btn-outline-light { .btn-outline-light {
box-shadow: none !important;
border-color: #999; border-color: #999;
margin: 0 3px 4px;
&.active, &.active,
&:hover { &:hover {
@ -39,6 +176,20 @@ header {
transition: fill 0.15s ease-in-out; transition: fill 0.15s ease-in-out;
} }
} }
small {
margin-left: 0.2rem;
font-weight: 700;
vertical-align: 1px;
}
.close {
float: none;
vertical-align: -2px;
color: #666;
line-height: 0;
margin-right: -0.3rem;
font-size: 1.3rem;
} }
} }
} }

View File

@ -1,15 +1,8 @@
@keyframes sk-bounce {
0%, 100% {
transform: scale(0.0);
} 50% {
transform: scale(1.0);
}
}
section.tabs { section.tabs {
margin-bottom: 1rem; margin-bottom: 1rem;
.sites { .sites {
position: relative;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
@ -35,26 +28,14 @@ section.tabs {
} }
} }
&.nav-site {
.nav-item {
.nav-link {
&.changed {
font-weight: normal;
}
&.active {
font-weight: 700;
}
}
}
}
&.nav-site-tab { &.nav-site-tab {
.nav-item { .nav-item {
.nav-link { .nav-link {
&:hover { &:hover {
@include media-breakpoint-up(xl) {
background-color: #f8f8f8; background-color: #f8f8f8;
} }
}
&.active { &.active {
@include media-breakpoint-up(xl) { @include media-breakpoint-up(xl) {
@ -149,7 +130,7 @@ section.tabs {
} }
} }
.tab-content { .tab-content {
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem 0.25rem;
border-left: 1px solid #dee2e6; border-left: 1px solid #dee2e6;
border-right: 1px solid #dee2e6; border-right: 1px solid #dee2e6;
border-bottom: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;
@ -157,10 +138,6 @@ section.tabs {
border-bottom-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem;
&.site-content { &.site-content {
padding-bottom: 0.75rem;
}
&.site-tab-content {
background-color: #f8f8f8; background-color: #f8f8f8;
.form-group { .form-group {
@ -208,7 +185,7 @@ section.tabs {
} }
.col-form-label-sm { .col-form-label-sm {
padding-top: 0; padding-top: 0.2rem;
padding-bottom: 0; padding-bottom: 0;
} }
@ -261,40 +238,6 @@ section.tabs {
} }
} }
section.loader {
position: fixed;
z-index: 1;
bottom: 25%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
.spinner {
width: 50px;
height: 50px;
position: relative;
margin: 100px auto;
.double-bounce1,
.double-bounce2 {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #999;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
animation: sk-bounce 2.0s infinite ease-in-out;
}
.double-bounce2 {
animation-delay: -1.0s;
}
}
}
main { main {
flex: 1 1 auto; flex: 1 1 auto;
opacity: 0; opacity: 0;
@ -317,6 +260,25 @@ main {
.commands { .commands {
margin-bottom: 1rem; margin-bottom: 1rem;
line-height: 1.35;
.step {
counter-reset: step-command-counter;
.counter {
display: inline-block;
margin-top: 0.15rem;
&::before {
counter-increment: step-command-counter;
content: counter(step-command-counter);
}
}
& > span:first-of-type .counter {
margin-top: 0;
}
}
} }
.file { .file {
@ -344,7 +306,7 @@ main {
code { code {
display: block; display: block;
padding: 0.6rem; padding: 8px 8px 12px;
-moz-tab-size: 4; -moz-tab-size: 4;
tab-size: 4; tab-size: 4;
overflow: visible; overflow: visible;

View File

@ -5,30 +5,6 @@ aside.sidebar {
margin-top: 0; margin-top: 0;
} }
.github-link {
text-align: center;
font-size: 1rem;
margin-bottom: 0.5rem;
small {
font-size: 90%;
}
img {
height: 1.2rem;
vertical-align: -4px;
}
}
.github-star {
width: 144px;
height: 30px;
display: block;
border: 0;
overflow: hidden;
margin: 0 auto 0.25rem;
}
.buttons { .buttons {
text-align: center; text-align: center;
margin-top: 1.5rem; margin-top: 1.5rem;

168
resources/scss/_steps.scss Normal file
View File

@ -0,0 +1,168 @@
section.steps {
ol {
display: flex;
flex-direction: row;
list-style: none;
counter-reset: steps-counter;
padding: 60px 0 0;
&[data-active-step="download"],
&[data-active-step="ssl"],
&[data-active-step="certbot"],
&[data-active-step="live"] {
li.download {
div {
background-color: #000;
border-color: #000;
svg {
stroke: #fff;
}
}
}
}
&[data-active-step="ssl"],
&[data-active-step="certbot"],
&[data-active-step="live"] {
li.ssl {
div {
background-color: #000;
border-color: #000;
svg {
stroke: #fff;
}
}
}
}
&[data-active-step="certbot"],
&[data-active-step="live"] {
li.certbot {
div {
background-color: #000;
border-color: #000;
svg {
stroke: #fff;
}
}
}
}
&[data-active-step="live"] {
li.live {
div {
background-color: #000;
border-color: #000;
svg {
stroke: #fff;
}
}
}
}
&[data-active-step="ssl"] {
li.download::after,
li.ssl::before {
background-color: #000;
}
}
&[data-active-step="certbot"] {
li.download::after,
li.ssl::before,
li.ssl::after,
li.certbot::before {
background-color: #000;
}
}
&[data-active-step="live"] {
li.download::after,
li.ssl::before,
li.ssl::after,
li.certbot::before,
li.certbot::after,
li.live::before {
background-color: #000;
}
}
li {
display: block;
position: relative;
flex: 1 1 auto;
counter-increment: steps-counter;
list-style-type: none;
text-align: center;
cursor: pointer;
font-size: 0.9rem;
@include media-breakpoint-up(sm) {
font-size: inherit;
}
&::before,
&::after {
content: '';
display: block;
height: 2px;
width: 50%;
position: absolute;
top: -35px;
background-color: #dee2e6;
z-index: 0;
transition: background-color 0.15s ease-in-out;
}
&::before {
right: 50%;
}
&::after {
left: 50%;
}
&:first-child::before,
&:last-child::after {
display: none;
}
.counter::before {
content: counter(steps-counter) '. ';
font-weight: 700;
}
.circle {
position: absolute;
z-index: 1;
left: 50%;
transform: translateX(-50%);
top: -50px;
width: 40px;
height: 40px;
border: 1px solid #dee2e6;
border-radius: 50%;
background-color: #f8f8f8;
transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
@include media-breakpoint-up(sm) {
top: -60px;
width: 50px;
height: 50px;
}
svg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60%;
}
}
}
}
}

View File

@ -8,6 +8,7 @@
@import 'body'; @import 'body';
@import 'header'; @import 'header';
@import 'steps';
@import 'main'; @import 'main';
@import 'sidebar'; @import 'sidebar';
@import 'footer'; @import 'footer';