3391 lines
252 KiB
HTML
3391 lines
252 KiB
HTML
|
<!DOCTYPE html><html lang="fr">
|
|||
|
<head><meta charset="utf-8">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>Serveur Local Debian Stretch 64bits domaine xoyaz.xyz - YannStatic</title>
|
|||
|
|
|||
|
<meta name="description" content="ASRock QC5000M Quad-Core APU">
|
|||
|
<link rel="canonical" href="https://static.rnmkcy.eu/2019/03/09/Debian-Stretch-64bits-Serveur-Local-srvxo-domaine-xoyaz.xyz.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
|
|||
|
|
|||
|
<!-- - include head/favicon.html - -->
|
|||
|
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
|
|||
|
<!-- end custom head snippets --><script>(function() {
|
|||
|
window.isArray = function(val) {
|
|||
|
return Object.prototype.toString.call(val) === '[object Array]';
|
|||
|
};
|
|||
|
window.isString = function(val) {
|
|||
|
return typeof val === 'string';
|
|||
|
};
|
|||
|
|
|||
|
window.hasEvent = function(event) {
|
|||
|
return 'on'.concat(event) in window.document;
|
|||
|
};
|
|||
|
|
|||
|
window.isOverallScroller = function(node) {
|
|||
|
return node === document.documentElement || node === document.body || node === window;
|
|||
|
};
|
|||
|
|
|||
|
window.isFormElement = function(node) {
|
|||
|
var tagName = node.tagName;
|
|||
|
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
|
|||
|
};
|
|||
|
|
|||
|
window.pageLoad = (function () {
|
|||
|
var loaded = false, cbs = [];
|
|||
|
window.addEventListener('load', function () {
|
|||
|
var i;
|
|||
|
loaded = true;
|
|||
|
if (cbs.length > 0) {
|
|||
|
for (i = 0; i < cbs.length; i++) {
|
|||
|
cbs[i]();
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
return {
|
|||
|
then: function(cb) {
|
|||
|
cb && (loaded ? cb() : (cbs.push(cb)));
|
|||
|
}
|
|||
|
};
|
|||
|
})();
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
window.throttle = function(func, wait) {
|
|||
|
var args, result, thisArg, timeoutId, lastCalled = 0;
|
|||
|
|
|||
|
function trailingCall() {
|
|||
|
lastCalled = new Date;
|
|||
|
timeoutId = null;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
}
|
|||
|
return function() {
|
|||
|
var now = new Date,
|
|||
|
remaining = wait - (now - lastCalled);
|
|||
|
|
|||
|
args = arguments;
|
|||
|
thisArg = this;
|
|||
|
|
|||
|
if (remaining <= 0) {
|
|||
|
clearTimeout(timeoutId);
|
|||
|
timeoutId = null;
|
|||
|
lastCalled = now;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
} else if (!timeoutId) {
|
|||
|
timeoutId = setTimeout(trailingCall, remaining);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var Set = (function() {
|
|||
|
var add = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (data[i] === item) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
this.size ++;
|
|||
|
data.push(item);
|
|||
|
return data;
|
|||
|
};
|
|||
|
|
|||
|
var Set = function(data) {
|
|||
|
this.size = 0;
|
|||
|
this._data = [];
|
|||
|
var i;
|
|||
|
if (data.length > 0) {
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
add.call(this, data[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
Set.prototype.add = add;
|
|||
|
Set.prototype.get = function(index) { return this._data[index]; };
|
|||
|
Set.prototype.has = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (this.get(i) === item) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
};
|
|||
|
Set.prototype.is = function(map) {
|
|||
|
if (map._data.length !== this._data.length) { return false; }
|
|||
|
var i, j, flag, tData = this._data, mData = map._data;
|
|||
|
for (i = 0; i < tData.length; i++) {
|
|||
|
for (flag = false, j = 0; j < mData.length; j++) {
|
|||
|
if (tData[i] === mData[j]) {
|
|||
|
flag = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!flag) { return false; }
|
|||
|
}
|
|||
|
return true;
|
|||
|
};
|
|||
|
Set.prototype.values = function() {
|
|||
|
return this._data;
|
|||
|
};
|
|||
|
return Set;
|
|||
|
})();
|
|||
|
|
|||
|
window.Lazyload = (function(doc) {
|
|||
|
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
|
|||
|
var createNode = function(name, attrs) {
|
|||
|
var node = doc.createElement(name), attr;
|
|||
|
for (attr in attrs) {
|
|||
|
if (attrs.hasOwnProperty(attr)) {
|
|||
|
node.setAttribute(attr, attrs[attr]);
|
|||
|
}
|
|||
|
}
|
|||
|
return node;
|
|||
|
};
|
|||
|
var end = function(type, url) {
|
|||
|
var s, q, qi, cbs, i, j, cur, val, flag;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
s[url] = true;
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (cur.urls.has(url)) {
|
|||
|
qi = cur, val = qi.urls.values();
|
|||
|
qi && (cbs = qi.callbacks);
|
|||
|
for (flag = true, j = 0; j < val.length; j++) {
|
|||
|
cur = val[j];
|
|||
|
if (!s[cur]) {
|
|||
|
flag = false;
|
|||
|
}
|
|||
|
}
|
|||
|
if (flag && cbs && cbs.length > 0) {
|
|||
|
for (j = 0; j < cbs.length; j++) {
|
|||
|
cbs[j].call(context);
|
|||
|
}
|
|||
|
qi.load = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
var load = function(type, urls, callback) {
|
|||
|
var s, q, qi, node, i, cur,
|
|||
|
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (_urls.is(cur.urls)) {
|
|||
|
qi = cur;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
val = _urls.values();
|
|||
|
if (qi) {
|
|||
|
callback && (qi.load || qi.callbacks.push(callback));
|
|||
|
callback && (qi.load && callback());
|
|||
|
} else {
|
|||
|
q.push({
|
|||
|
urls: _urls,
|
|||
|
callbacks: callback ? [callback] : [],
|
|||
|
load: false
|
|||
|
});
|
|||
|
for (i = 0; i < val.length; i++) {
|
|||
|
node = null, url = val[i];
|
|||
|
if (s[url] === undefined) {
|
|||
|
(type === 'js' ) && (node = createNode('script', { src: url }));
|
|||
|
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
|
|||
|
if (node) {
|
|||
|
node.onload = (function(type, url) {
|
|||
|
return function() {
|
|||
|
end(type, url);
|
|||
|
};
|
|||
|
})(type, url);
|
|||
|
(doc.head || doc.body).appendChild(node);
|
|||
|
s[url] = false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
return {
|
|||
|
js: function(url, callback) {
|
|||
|
load('js', url, callback);
|
|||
|
},
|
|||
|
css: function(url, callback) {
|
|||
|
load('css', url, callback);
|
|||
|
}
|
|||
|
};
|
|||
|
})(this.document);
|
|||
|
})();
|
|||
|
</script><script>
|
|||
|
(function() {
|
|||
|
var TEXT_VARIABLES = {
|
|||
|
version: '2.2.6',
|
|||
|
sources: {
|
|||
|
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
|
|||
|
jquery: '/assets/js/jquery.min.js',
|
|||
|
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
|
|||
|
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
|
|||
|
gitalk: {
|
|||
|
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
|
|||
|
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
|
|||
|
},
|
|||
|
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
|
|||
|
},
|
|||
|
site: {
|
|||
|
toc: {
|
|||
|
selectors: 'h1,h2,h3'
|
|||
|
}
|
|||
|
},
|
|||
|
paths: {
|
|||
|
search_js: '/assets/search.js'
|
|||
|
}
|
|||
|
};
|
|||
|
window.TEXT_VARIABLES = TEXT_VARIABLES;
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<div class="root" data-is-touch="false">
|
|||
|
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
|
|||
|
|
|||
|
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
|
|||
|
<div class="header__title">
|
|||
|
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
|
|||
|
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
|
|||
|
<!-- Champ de recherche -->
|
|||
|
<div id="searchbox" class="search search--dark" style="visibility: visible">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header"></div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<!-- <div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div> -->
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
json: '/search.json',
|
|||
|
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date} {title}</a></li>'
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a></li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
|
|||
|
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
|
|||
|
</nav></div>
|
|||
|
</header>
|
|||
|
|
|||
|
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
|
|||
|
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
|
|||
|
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">Serveur Local Debian Stretch 64bits domaine xoyaz.xyz</h1></header></div><meta itemprop="headline" content="Serveur Local Debian Stretch 64bits domaine xoyaz.xyz"><div class="article__info clearfix"><ul class="left-col menu"><li>
|
|||
|
<a class="button button--secondary button--pill button--sm"
|
|||
|
href="/archive.html?tag=debian">debian</a>
|
|||
|
</li><li>
|
|||
|
<a class="button button--secondary button--pill button--sm"
|
|||
|
href="/archive.html?tag=serveur">serveur</a>
|
|||
|
</li></ul><ul class="right-col menu"><li>
|
|||
|
<i class="far fa-calendar-alt"></i> <span title="Création" style="color:#FF00FF"> 9 mars 2019</span></li></ul></div><meta itemprop="datePublished" content="2019-03-09T00:00:00+01:00">
|
|||
|
<meta itemprop="keywords" content="debian,serveur"><div class="js-article-content">
|
|||
|
<div class="layout--article"><!-- start custom article top snippet -->
|
|||
|
<style>
|
|||
|
#myBtn {
|
|||
|
display: none;
|
|||
|
position: fixed;
|
|||
|
bottom: 10px;
|
|||
|
right: 10px;
|
|||
|
z-index: 99;
|
|||
|
font-size: 12px;
|
|||
|
font-weight: bold;
|
|||
|
border: none;
|
|||
|
outline: none;
|
|||
|
background-color: white;
|
|||
|
color: black;
|
|||
|
cursor: pointer;
|
|||
|
padding: 5px;
|
|||
|
border-radius: 4px;
|
|||
|
}
|
|||
|
|
|||
|
#myBtn:hover {
|
|||
|
background-color: #555;
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
<button onclick="topFunction()" id="myBtn" title="Haut de page">⇧</button>
|
|||
|
|
|||
|
<script>
|
|||
|
//Get the button
|
|||
|
var mybutton = document.getElementById("myBtn");
|
|||
|
|
|||
|
// When the user scrolls down 20px from the top of the document, show the button
|
|||
|
window.onscroll = function() {scrollFunction()};
|
|||
|
|
|||
|
function scrollFunction() {
|
|||
|
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
|
|||
|
mybutton.style.display = "block";
|
|||
|
} else {
|
|||
|
mybutton.style.display = "none";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// When the user clicks on the button, scroll to the top of the document
|
|||
|
function topFunction() {
|
|||
|
document.body.scrollTop = 0;
|
|||
|
document.documentElement.scrollTop = 0;
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
<!-- end custom article top snippet -->
|
|||
|
<div class="article__content" itemprop="articleBody"><details>
|
|||
|
<summary><b>Afficher/cacher Sommaire</b></summary>
|
|||
|
<!-- affichage sommaire -->
|
|||
|
<div class="toc-aside js-toc-root"></div>
|
|||
|
</details><h2 id="asrock-qc5000m-quad-core-apu">ASRock QC5000M Quad-Core APU</h2>
|
|||
|
|
|||
|
<p><a href="https://static.rnmkcy.eu/files/QC5000M.pdf">ASRock QC5000M (pdf)</a></p>
|
|||
|
|
|||
|
<p><img src="/images/asrock-qc500m.png" alt="ASRock QC5000M" title="ASRock QC5000M" /></p>
|
|||
|
|
|||
|
<h2 id="debian-stretch">Debian Stretch</h2>
|
|||
|
|
|||
|
<p>Boot sur clé “debian 9”</p>
|
|||
|
|
|||
|
<p>Utilisation disque entier LVM (Sata SSD 120Go)<br />
|
|||
|
30Go ext4 root<br />
|
|||
|
80Go ext4 home<br />
|
|||
|
256Mo ext2 boot</p>
|
|||
|
|
|||
|
<p>Serveur SSH<br />
|
|||
|
Utilitaires usuels du système</p>
|
|||
|
|
|||
|
<p>Reboot<br />
|
|||
|
Connexion xoadmin</p>
|
|||
|
|
|||
|
<p>enp3s0 :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>adresse ip : 192.168.0.30</li>
|
|||
|
<li>mac add : 70:85:c2:53:cb:80</li>
|
|||
|
<li>inet6 : fe80::7285:c2ff:fe53:cb80</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="mise-à-jour-debian-et-installation-des-utilitaires">Mise à jour Debian et installation des utilitaires</h3>
|
|||
|
|
|||
|
<p>Première connexion via SSH</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh xoadmin@192.168.0.30
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Màj</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt upgrade
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Firmware Realtek</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "deb http://httpredir.debian.org/debian/ stretch main contrib non-free" >> /etc/apt/sources.list
|
|||
|
apt update
|
|||
|
apt install firmware-realtek
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer utilitaires</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install rsync curl tmux jq figlet git mailutils dnsutils netcat -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Droits d’accès sudo à l’utilisateur <strong>xoadmin</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install sudo
|
|||
|
echo "xoadmin ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="configurer-locales-fr">Configurer Locales (fr)</h3>
|
|||
|
|
|||
|
<p>Locales : <strong>fr_FR.UTF-8</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dpkg-reconfigure locales
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Generating locales <span class="o">(</span>this might take a <span class="k">while</span><span class="o">)</span>...
|
|||
|
fr_FR.UTF-8... <span class="k">done
|
|||
|
</span>Generation complete.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="europeparis-timezone-tzdata">Europe/Paris (TimeZone tzdata)</h3>
|
|||
|
|
|||
|
<p>Europe/Paris</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dpkg-reconfigure tzdata
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Current default time zone: 'Europe/Paris'
|
|||
|
Local time is now: Tue Mar 5 15:48:25 CET 2019.
|
|||
|
Universal Time is now: Tue Mar 5 14:48:25 UTC 2019.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="adressage-ipv6">Adressage ipv6</h3>
|
|||
|
|
|||
|
<p><img src="/images/ipv6.png" alt="ipv6" /></p>
|
|||
|
|
|||
|
<p>La carte n’est joignable de l’internet que par son adresse IPV6<br />
|
|||
|
NextHop Freebox permet d’attribuer une adresse IPV6<br />
|
|||
|
Adresse IPV6 Box <strong>fe80::224:d4ff:fea6:aa20</strong></p>
|
|||
|
|
|||
|
<p>Préfixe : <strong>2a01:e34:eebf:df5::/64</strong><br />
|
|||
|
NextHop : <strong>fe80::7285:c2ff:fe53:cb80</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/network/interfaces
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># This file describes the network interfaces available on your system
|
|||
|
# and how to activate them. For more information, see interfaces(5).
|
|||
|
|
|||
|
source /etc/network/interfaces.d/*
|
|||
|
|
|||
|
# The loopback network interface
|
|||
|
auto lo
|
|||
|
iface lo inet loopback
|
|||
|
|
|||
|
# The primary network interface
|
|||
|
allow-hotplug enp3s0
|
|||
|
iface enp3s0 inet dhcp
|
|||
|
# This is an autoconfigured IPv6 interface
|
|||
|
# iface enp3s0 inet6 auto
|
|||
|
iface enp3s0 inet6 static
|
|||
|
address 2a01:e34:eebf:df5::1
|
|||
|
netmask 64
|
|||
|
post-up ip -6 route add default via fe80::224:d4ff:fea6:aa20 dev enp3s0
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrer la machine</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl reboot
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier l’adresse inet6</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ip addr
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
|
|||
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
|||
|
inet 127.0.0.1/8 scope host lo
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 ::1/128 scope host
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
|||
|
link/ether 70:85:c2:53:cb:80 brd ff:ff:ff:ff:ff:ff
|
|||
|
inet 192.168.0.30/24 brd 192.168.0.255 scope global enp3s0
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 2a01:e34:eebf:df5::1/64 scope global
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 fe80::7285:c2ff:fe53:cb80/64 scope link
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
3: enp4s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
|
|||
|
link/ether 6c:b3:11:32:04:c8 brd ff:ff:ff:ff:ff:ff
|
|||
|
4: enp4s0f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
|
|||
|
link/ether 6c:b3:11:32:04:c9 brd ff:ff:ff:ff:ff:ff
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="hostname-xoyazxyz">Hostname xoyaz.xyz</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> _ _
|
|||
|
| |__ ___ ___| |_ _ __ __ _ _ __ ___ ___
|
|||
|
| '_ \ / _ \/ __| __| '_ \ / _` | '_ ` _ \ / _ \
|
|||
|
| | | | (_) \__ \ |_| | | | (_| | | | | | | __/
|
|||
|
|_| |_|\___/|___/\__|_| |_|\__,_|_| |_| |_|\___|
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier <strong>hostname</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostnamectl set-hostname --static xoyaz.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier <strong>/etc/hosts</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /etc/hosts
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>127.0.0.1 localhost
|
|||
|
127.0.1.1 xoyaz.xyz srvxo
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifications</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostnamectl
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Static hostname: xoyaz.xyz
|
|||
|
Icon name: computer-desktop
|
|||
|
Chassis: desktop
|
|||
|
Machine ID: 458ff564e0a049238e954906d88c7c32
|
|||
|
Boot ID: 3b8498a5d3cd4872a6aab38d73824a9c
|
|||
|
Operating System: Debian GNU/Linux 9 (stretch)
|
|||
|
Kernel: Linux 4.9.0-4-amd64
|
|||
|
Architecture: x86-64
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostname --fqdn
|
|||
|
xoyaz.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="dns-ovh">DNS OVH</h3>
|
|||
|
|
|||
|
<p><img src="/images/dns-logo.png" alt="dns" /></p>
|
|||
|
|
|||
|
<p>Le domaine <strong>xoyaz.xyz</strong> pointe sur l’adresse IPV6 <strong>2a01:e34:eebf:df5::1</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$TTL 3600
|
|||
|
@ IN SOA dns106.ovh.net. tech.ovh.net. (2019030600 86400 3600 3600000 300)
|
|||
|
3600 IN NS ns106.ovh.net.
|
|||
|
3600 IN NS dns106.ovh.net.
|
|||
|
3600 IN MX 10 xoyaz.xyz.
|
|||
|
3600 IN AAAA 2a01:e34:eebf:df5::1
|
|||
|
* 3600 IN CNAME xoyaz.xyz.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="ssh-avec-clé">SSH avec clé</h3>
|
|||
|
|
|||
|
<p><img src="/images/ssh_logo1.png" alt="ssh" />+<img src="/images/ssh-keys.png" alt="clés" /></p>
|
|||
|
|
|||
|
<p><u>sur l'ordinateur de bureau</u>
|
|||
|
Générer une paire de clé curve25519-sha256 (ECDH avec Curve25519 et SHA2) nommé <strong>xoyaz</strong> pour une liaison SSH avec le serveur KVM.<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">ssh-keygen -t ed25519 -o -a 100 -f ~/.ssh/xoyaz</code><br />
|
|||
|
Envoyer la clé publique sur le serveur KVM <br />
|
|||
|
<code class="language-plaintext highlighter-rouge">scp ~/.ssh/xoyaz.pub xoadmin@192.168.0.30:/home/xoadmin/</code></p>
|
|||
|
|
|||
|
<p><u>sur le serveur **xoyaz**</u><br />
|
|||
|
Copier le contenu de la clé publique dans /home/$USER/.ssh/authorized_keys<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">$ cd ~</code><br />
|
|||
|
Sur le KVM ,créer un dossier .ssh</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir .ssh
|
|||
|
cat /home/$USER/xoyaz.pub >> /home/$USER/.ssh/authorized_keys
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>et donner les droits<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">chmod 600 /home/$USER/.ssh/authorized_keys</code><br />
|
|||
|
effacer le fichier de la clé<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">rm /home/$USER/xoyaz.pub</code><br />
|
|||
|
Modifier la configuration serveur SSH<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo nano /etc/ssh/sshd_config</code><br />
|
|||
|
Modifier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Port = 55034
|
|||
|
PasswordAuthentication no
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer openSSH<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo systemctl restart sshd</code><br />
|
|||
|
Accès depuis le poste distant avec la clé privée<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">ssh -p 55034 -i ~/.ssh/xoyaz xoadmin@192.168.0.30</code></p>
|
|||
|
|
|||
|
<h3 id="exécution-script-sur-connexion-ssh">Exécution script sur connexion SSH</h3>
|
|||
|
|
|||
|
<p>Exécuter un fichier <em>utilisateur</em> nommé <strong>$HOME/.ssh/rc</strong> si <em>présent</em><br />
|
|||
|
Pour <em>tous les utilisateurs</em> exécuter un fichier nommé <strong>/etc/ssh/sshrc</strong> si <em>présent</em><br />
|
|||
|
Installer les utilitaires <em>curl jq figlet</em></p>
|
|||
|
|
|||
|
<p>Créer dossier si connexion par clé non installée<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">mkdir -p ~/.ssh</code><br />
|
|||
|
Le batch<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">nano ~/.ssh/rc</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
|
|||
|
|
|||
|
#clear
|
|||
|
PROCCOUNT=`ps -Afl | wc -l` # nombre de lignes
|
|||
|
PROCCOUNT=`expr $PROCCOUNT - 5` # on ote les non concernées
|
|||
|
GROUPZ=`users`
|
|||
|
ipinfo=$(curl -s ipinfo.io) # info localisation format json
|
|||
|
publicip=$(echo $ipinfo | jq -r '.ip') # extraction des données , installer préalablement "jq"
|
|||
|
ville=$(echo $ipinfo | jq -r '.city')
|
|||
|
pays=$(echo $ipinfo | jq -r '.country')
|
|||
|
cpuname=`cat /proc/cpuinfo |grep 'model name' | cut -d: -f2 | sed -n 1p`
|
|||
|
iplink=`ip link show |grep -m 1 "2:" | awk '{print $2}' | cut -d: -f1`
|
|||
|
|
|||
|
echo "\033[0m\033[1;31m"
|
|||
|
figlet "`hostname --fqdn`"
|
|||
|
echo "\033[0m
|
|||
|
\033[1;35m \033[1;37mHostname \033[1;35m= \033[1;32m`hostname`
|
|||
|
\033[1;35m \033[1;37mWired IpV4 \033[1;35m= \033[1;32m`ip addr show $iplink | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1`
|
|||
|
\033[1;35m \033[1;37mWired IpV6 \033[1;35m= \033[1;32m`ip addr show $iplink | grep -E 'inet6' |grep -E 'scope link' | awk '{print $2}' | cut -d/ -f1`
|
|||
|
\033[1;35m \033[1;37mKernel \033[1;35m= \033[1;32m`uname -r`
|
|||
|
\033[1;35m \033[1;37mDebian \033[1;35m= \033[1;32m`cat /etc/debian_version`
|
|||
|
\033[1;35m \033[1;37mUptime \033[1;35m= \033[1;32m`uptime | sed 's/.*up ([^,]*), .*/1/' | sed -e 's/^[ \t]*//'`
|
|||
|
\033[1;35m \033[1;37mCPU \033[1;35m= \033[1;32m`echo $cpuname`
|
|||
|
\033[1;35m \033[1;37mMemory Use \033[1;35m= \033[1;32m`free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'`
|
|||
|
\033[1;35m \033[1;37mUsername \033[1;35m= \033[1;32m`whoami`
|
|||
|
\033[1;35m \033[1;37mSessions \033[1;35m= \033[1;32m`who | grep $USER | wc -l`
|
|||
|
\033[1;35m \033[1;37mPublic IpV4 \033[1;35m= \033[1;32m`echo $publicip`
|
|||
|
\033[1;35m \033[1;37mPublic IpV6 \033[1;35m= \033[1;32m`ip addr show $iplink | grep -m 1 'inet6\b' | awk '{print $2}' | cut -d/ -f1`
|
|||
|
\033[0m"
|
|||
|
df -h /
|
|||
|
#curl fr.wttr.in/$ville?0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Effacer motd<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo rm /etc/motd</code><br />
|
|||
|
Déconnexion puis connexion</p>
|
|||
|
|
|||
|
<p><img src="/images/xoyaz-rc.png" alt="" width="60%" /></p>
|
|||
|
|
|||
|
<h3 id="certificats-letsencrypt">Certificats letsencrypt</h3>
|
|||
|
|
|||
|
<p><img src="/images/letsencrypt-logo1.png" alt="letsencrypt" /></p>
|
|||
|
|
|||
|
<p>Installation gestionnaire des certificats Let’s Encrypt</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~
|
|||
|
sudo -s # en mode super utilisateur
|
|||
|
apt install netcat socat # prérequis
|
|||
|
git clone https://github.com/Neilpang/acme.sh.git
|
|||
|
cd acme.sh
|
|||
|
./acme.sh --install # --nocron
|
|||
|
cd ..
|
|||
|
rm -rf acme.sh/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Se connecter sur l’api OVH pour les paramètres (clé et secret)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>export OVH_AK="votre application key"
|
|||
|
export OVH_AS="votre application secret"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Premier lancement pour la génération des certificats</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/root/.acme.sh/acme.sh --dns dns_ovh --issue --keylength ec-384 -d xoyaz.xyz -d '*.xoyaz.xyz'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
|
|||
|
[mercredi 17 octobre 2018, 14:05:32 (UTC+0200)] Please open this link to do authentication: https://eu.api.ovh.com/auth/?credentialToken=FQGXWob9QI9m1yg8NlmPN0GZOJRKEzMLdlsPoIJT2o2WuWBikcsJIMyICk6Z8K0Z
|
|||
|
[...]
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Connecter l’url ci-dessus, s’authentifier puis sélectionner “unlimited” et valider.Le message suivant dit s’afficher.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>OVH authentication Success !
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Lancer une seconde fois la génération des certificats et patienter quelques minutes…</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/root/.acme.sh/acme.sh --dns dns_ovh --issue --keylength ec-384 -d xoyaz.xyz -d '*.xoyaz.xyz'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les certificats sont disponibles</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[mardi 5 mars 2019, 16:48:13 (UTC+0100)] Your cert is in /root/.acme.sh/xoyaz.xyz_ecc/xoyaz.xyz.cer
|
|||
|
[mardi 5 mars 2019, 16:48:13 (UTC+0100)] Your cert key is in /root/.acme.sh/xoyaz.xyz_ecc/xoyaz.xyz.key
|
|||
|
[mardi 5 mars 2019, 16:48:14 (UTC+0100)] The intermediate CA cert is in /root/.acme.sh/xoyaz.xyz_ecc/ca.cer
|
|||
|
[mardi 5 mars 2019, 16:48:14 (UTC+0100)] And the full chain certs is there: /root/.acme.sh/xoyaz.xyz_ecc/fullchain.cer
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour un lancement manuel (ajout domaine, sous-domaine ou regénération des certificats)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
/root/.acme.sh/acme.sh --dns dns_ovh --issue --keylength ec-384 -d xoyaz.xyz -d *.xoyaz.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Un certificat Wildcard Let’s Encrypt qui se renouvelle automatiquement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -l
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>18 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="nginx-php7-mariadb">Nginx PHP7 mariadb</h3>
|
|||
|
|
|||
|
<p><img src="/images/nginx-php7-mariadb1.png" alt="lemp" /></p>
|
|||
|
|
|||
|
<p>Préalable</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install apt-transport-https
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="https://static.xoyaz.xyz/2018/12/Compilation-Nginx(avec-modules-dynamiques)+TLSv1.3+PHP7.3+MariaDB-sur-DebianStretch.html">Nginx (compilation),PHP7 et MariaDb</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Script</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s # Passer en mode super utilisateur (su ou sudo)
|
|||
|
wget -O install.sh "https://static.xoyaz.xyz/files/debian9-compilation-nginx-tls1.3-php7.3-MariaDB.sh.txt" # Télécharger le script
|
|||
|
chmod +x install.sh # Rendre le script exécutable
|
|||
|
./install.sh # Exécuter le script
|
|||
|
#******** Patienter **********
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="ssl-xoyazxyz">SSL xoyaz.xyz</h3>
|
|||
|
|
|||
|
<p><img src="/images/certificat-ssl.png" alt="SSL" /></p>
|
|||
|
|
|||
|
<p>Certificats sur les sites xoyaz.xyz</p>
|
|||
|
|
|||
|
<p>Ajout des certificats , création des liens</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo ln -s /root/.acme.sh/xoyaz.xyz_ecc/fullchain.cer /etc/ssl/private/xoyaz.xyz-fullchain.pem
|
|||
|
sudo ln -s /root/.acme.sh/xoyaz.xyz_ecc/xoyaz.xyz.key /etc/ssl/private/xoyaz.xyz-key.pem
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les fichiers de configurations ssl headers et nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/nginx/ssl_params
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ssl_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
|
|||
|
ssl_certificate_key /etc/ssl/private/xoyaz.xyz-key.pem;
|
|||
|
ssl_session_timeout 5m;
|
|||
|
ssl_session_cache shared:SSL:50m;
|
|||
|
ssl_prefer_server_ciphers on;
|
|||
|
|
|||
|
# Ciphers with modern compatibility
|
|||
|
# New protocol TLSv1.3
|
|||
|
ssl_protocols TLSv1.3 TLSv1.2;
|
|||
|
ssl_ciphers 'TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>entêtes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/nginx/header_params
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
|
|||
|
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
|
|||
|
# https://observatory.mozilla.org/
|
|||
|
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
|
|||
|
add_header Content-Security-Policy "upgrade-insecure-requests";
|
|||
|
add_header Content-Security-Policy-Report-Only "default-src https: data: 'unsafe-inline' 'unsafe-eval'";
|
|||
|
add_header X-Content-Type-Options nosniff;
|
|||
|
add_header X-XSS-Protection "1; mode=block";
|
|||
|
add_header X-Download-Options noopen;
|
|||
|
add_header X-Permitted-Cross-Domain-Policies none;
|
|||
|
add_header X-Frame-Options "SAMEORIGIN";
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On change le dossier racine</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir /var/www/default-www
|
|||
|
sudo mv /var/www/{index.html,info.php} /var/www/default-www/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Configuration de base avec SSL et sécurité + letsencrypt (renouvellement)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/nginx/conf.d/xoyaz.xyz.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 80;
|
|||
|
listen [::]:80;
|
|||
|
|
|||
|
## redirect http to https ##
|
|||
|
server_name xoyaz.xyz;
|
|||
|
return 301 https://$server_name$request_uri;
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 443 ssl http2;
|
|||
|
listen [::]:443 ssl http2;
|
|||
|
server_name xoyaz.xyz;
|
|||
|
|
|||
|
#### Locations
|
|||
|
# On cache les fichiers statiques
|
|||
|
location ~* \.(html|css|js|png|jpg|jpeg|gif|ico|svg|eot|woff|ttf)$ { expires max; }
|
|||
|
# On interdit les dotfiles
|
|||
|
location ~ /\. { deny all; }
|
|||
|
|
|||
|
include ssl_params;
|
|||
|
include header_params;
|
|||
|
# Diffie-Hellmann
|
|||
|
# Uncomment the following directive after DH generation
|
|||
|
# > openssl dhparam -out /etc/ssl/private/dh4096.pem -outform PEM -2 4096
|
|||
|
# ssl_dhparam /etc/ssl/private/dh4096.pem;
|
|||
|
|
|||
|
root /var/www/default-www ;
|
|||
|
index index.php index.html index.htm;
|
|||
|
location ~ \.php$ {
|
|||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|||
|
fastcgi_pass unix:/run/php/php7.3-fpm.sock; # PHP7.3
|
|||
|
fastcgi_index index.php;
|
|||
|
include fastcgi_params;
|
|||
|
fastcgi_param SCRIPT_FILENAME $request_filename;
|
|||
|
}
|
|||
|
|
|||
|
# if folder xoyaz.xyz.d , uncomment the following directive
|
|||
|
#include conf.d/xoyaz.xyz.d/*.conf;
|
|||
|
|
|||
|
access_log /var/log/nginx/xoyaz.xyz-access.log;
|
|||
|
error_log /var/log/nginx/xoyaz.xyz-error.log;
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Effacer ancien fichier de config</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm /etc/nginx/conf.d/default.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier et relancer nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
|
|||
|
sudo systemctl restart nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier le lien https://xoyaz.xyz , le tls 1.3</p>
|
|||
|
|
|||
|
<p><img src="/images/xoyaz.xyz-tlsv1.3.png" alt="" width="500" /></p>
|
|||
|
|
|||
|
<h3 id="parefeu-iptables-v4-v6">parefeu (iptables V4 V6)</h3>
|
|||
|
|
|||
|
<p><img src="/images/iptables1.png" alt="parefeu Iptables" width="100" /><br />
|
|||
|
<a href="https://static.xoyaz.xyz/2018/10/Pare-feu-iptables-IPv4-IPv6-versions-bureau-et-serveur.html">installer un parefeu serveur</a></p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>NOTE : Tous les ports sont OUVERTS en SORTIE vers l’extérieur</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Le script de base <strong>/usr/local/sbin/config_firewall</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/sh
|
|||
|
|
|||
|
###################
|
|||
|
# IPv4 #
|
|||
|
###################
|
|||
|
|
|||
|
# refuser input et forward par défaut, accepter output
|
|||
|
iptables -t filter -P INPUT DROP
|
|||
|
iptables -t filter -P FORWARD DROP
|
|||
|
iptables -t filter -P OUTPUT ACCEPT
|
|||
|
|
|||
|
# interface lo (loop) accessible
|
|||
|
iptables -A INPUT -i lo -j ACCEPT
|
|||
|
iptables -A OUTPUT -o lo -j ACCEPT
|
|||
|
|
|||
|
# maintenir les connexions établies
|
|||
|
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|||
|
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|||
|
|
|||
|
# accepter en entrée le ping (icmp), et les
|
|||
|
# connexions sur les ports nécessaires.
|
|||
|
iptables -A INPUT -p icmp --icmp-type echo-request -m conntrack --ctstate NEW -m limit --limit 1/s --limit-burst 1 -j ACCEPT
|
|||
|
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
|||
|
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|||
|
iptables -A INPUT -p tcp --dport 55034 -j ACCEPT
|
|||
|
iptables -A INPUT -p udp --dport 55034 -j ACCEPT
|
|||
|
|
|||
|
# accepter en sortie le ping, les requêtes HTTP(S), DNS,
|
|||
|
# et les connexions sur les ports nécessaires.
|
|||
|
iptables -A OUTPUT -p icmp --icmp-type echo-request -m conntrack --ctstate NEW -j ACCEPT
|
|||
|
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
|
|||
|
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
|
|||
|
|
|||
|
|
|||
|
###################
|
|||
|
# IPv6 #
|
|||
|
###################
|
|||
|
|
|||
|
# refuser input et forward par défaut, accepter output
|
|||
|
ip6tables -t filter -P INPUT DROP
|
|||
|
ip6tables -t filter -P FORWARD DROP
|
|||
|
ip6tables -t filter -P OUTPUT ACCEPT
|
|||
|
|
|||
|
# interface lo (loop) accessible
|
|||
|
ip6tables -A INPUT -i lo -j ACCEPT
|
|||
|
ip6tables -A OUTPUT -o lo -j ACCEPT
|
|||
|
|
|||
|
# maintenir les connexions établies
|
|||
|
ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|||
|
ip6tables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|||
|
|
|||
|
# NDP pour toute interface de type broadcast
|
|||
|
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT
|
|||
|
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT
|
|||
|
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT
|
|||
|
|
|||
|
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbour-solicitation -j ACCEPT
|
|||
|
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbour-advertisement -j ACCEPT
|
|||
|
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT
|
|||
|
|
|||
|
# accepter en entrée le ping (icmpv6), les
|
|||
|
# connexions entrantes déjà établies et les connexions sur les ports nécessaires.
|
|||
|
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -m conntrack --ctstate NEW -m limit --limit 1/s --limit-burst 1 -j ACCEPT
|
|||
|
ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
|
|||
|
ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|||
|
ip6tables -A INPUT -p tcp --dport 55034 -j ACCEPT
|
|||
|
ip6tables -A INPUT -p udp --dport 55034 -j ACCEPT
|
|||
|
|
|||
|
# accepter en sortie le ping, les requêtes HTTP(S), DNS,
|
|||
|
# et les connexions sur les ports nécessaires.
|
|||
|
ip6tables -t filter -A OUTPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT
|
|||
|
ip6tables -A OUTPUT -p tcp --dport 80 -j ACCEPT
|
|||
|
ip6tables -A OUTPUT -p tcp --dport 443 -j ACCEPT
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Script</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /usr/local/sbin/config_firewall # droits en exécution
|
|||
|
/usr/local/sbin/config_firewall # exécution
|
|||
|
iptables -L # affiche règles ipv4
|
|||
|
ip6tables -L # affiche règles ipv6
|
|||
|
apt-get install iptables-persistent # pour la persistance au redémarrage
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="ipv4-statique">IPV4 statique</h3>
|
|||
|
|
|||
|
<p>Modifier la configuration réseau pour avoir une adresse ip statique</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/network/interfaces
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># This file describes the network interfaces available on your system
|
|||
|
# and how to activate them. For more information, see interfaces(5).
|
|||
|
|
|||
|
source /etc/network/interfaces.d/*
|
|||
|
|
|||
|
# The loopback network interface
|
|||
|
auto lo
|
|||
|
iface lo inet loopback
|
|||
|
|
|||
|
# The primary network interface
|
|||
|
allow-hotplug enp3s0
|
|||
|
iface enp3s0 inet static
|
|||
|
address 192.168.0.30
|
|||
|
netmask 255.255.255.0
|
|||
|
gateway 192.168.0.254
|
|||
|
# IPv6 interface
|
|||
|
iface enp3s0 inet6 static
|
|||
|
address 2a01:e34:eebf:df5::1
|
|||
|
netmask 64
|
|||
|
post-up ip -6 route add default via fe80::224:d4ff:fea6:aa20 dev enp3s0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer le service</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo service networking restart
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
|
|||
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
|||
|
inet 127.0.0.1/8 scope host lo
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 ::1/128 scope host
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
|||
|
link/ether 70:85:c2:53:cb:80 brd ff:ff:ff:ff:ff:ff
|
|||
|
inet 192.168.0.30/24 brd 192.168.0.255 scope global enp3s0
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 2a01:e34:eebf:df5::1/64 scope global
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 2a01:e34:eebf:df0:7285:c2ff:fe53:cb80/64 scope global mngtmpaddr dynamic
|
|||
|
valid_lft 84689sec preferred_lft 84689sec
|
|||
|
inet6 fe80::7285:c2ff:fe53:cb80/64 scope link
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
3: enp4s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
|
|||
|
link/ether 6c:b3:11:32:04:c8 brd ff:ff:ff:ff:ff:ff
|
|||
|
4: enp4s0f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
|
|||
|
link/ether 6c:b3:11:32:04:c9 brd ff:ff:ff:ff:ff:ff
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="dns-unbound">DNS Unbound</h3>
|
|||
|
|
|||
|
<p><img src="/images/unbound-250.png" alt="" width="100" /><br />
|
|||
|
<a href="/2018/04/27/unbound-resolveur-DNS.html">Résolveur DNS Unbound</a></p>
|
|||
|
|
|||
|
<p>On ne peut plus modifier le fichier /etc/resolv.conf , pour ajouter des serveurs dns à celui en place (127.0.0.1) , il faut ajouter la ligne suivante (après la ligne ‘gateway’) au fichier ** /etc/network/interfaces**</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dns-nameservers 127.0.0.1 9.9.9.9 80.67.169.12 80.67.169.40
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Adaptater vos serveurs dns séparés par un espace sauf le premier de la liste. <em>dns-nameservers</em> prend <strong>toujours un s</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3 id="postfix-pour-uniquement-envoyer-des-messages">Postfix pour uniquement envoyer des messages</h3>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="/2019/03/06/Debian-Stretch-Postfix-comme-Serveur-SMTP-pour-uniquement-envoyer-des-messages.html">Postfix en tant que serveur SMTP d’envoi message uniquement sur Debian 9</a></li>
|
|||
|
<li><a href="/2019/03/06/OpenDkim-Spf.html">Opendkim ,identifier ses mails avec le principe DKIM</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="configuration-dns-et-box">Configuration dns et box</h3>
|
|||
|
|
|||
|
<p>DNS OVH (spf et dkim) pour tenir compte de la messagerie</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$TTL 3600
|
|||
|
@ IN SOA dns106.ovh.net. tech.ovh.net. (2019030604 86400 3600 3600000 300)
|
|||
|
3600 IN NS dns106.ovh.net.
|
|||
|
3600 IN NS ns106.ovh.net.
|
|||
|
3600 IN MX 10 xoyaz.xyz.
|
|||
|
IN A 78.235.240.223
|
|||
|
3600 IN AAAA 2a01:e34:eebf:df5::1
|
|||
|
600 IN TXT "v=spf1 a mx ip4:78.235.240.223 ip6:2a01:e34:eebf:df5::1 -all"
|
|||
|
* 3600 IN CNAME xoyaz.xyz.
|
|||
|
mail._domainkey 3600 IN TXT ( "v=DKIM1; k=rsa; h=sha256; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoL+I8An+opPnV+qZe3fAzrAwDtwiPFAXtcgO1979kILy0wFLC0S+g2hzGSkaZAtwD27MWPR+IlSkEFeXhRwsVPM5Ryu7yeEap+mj9B8oqhoPTQP9UNR8b2YJxoc86WakuTTjJUykJ2EU8K4JX3PYRiYd2n9CKEIBy1/mWZnzmOtN047K8q" "MkXV2csZ+si4U1PhXy3tI4n1sHU6iiXNwydecsGdhoMlk18jfiQx0a2He+rKxSN4iUbfO1J+9rAWZZHLecV0nukJUbzpD32+2dW3Zx545hVVaUvhZCARAZc8BH53c4lWjn37coZLmLTQhdhS8tH4wev0pN0hyNicf6yQIDAQAB" )
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Box</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Reverse DNS : xoyaz.xyz</li>
|
|||
|
<li>DMZ : 192.168.0.30</li>
|
|||
|
<li>Déblocage SMTP (port 25 ouvert)</li>
|
|||
|
<li>DNS 1 2 3 : 9.9.9.9 80.67.169.12 80.67.169.40</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h2 id="nfs-serveur">NFS serveur</h2>
|
|||
|
|
|||
|
<p><img src="/images/nfs-ufw.png" alt="" /><br />
|
|||
|
<em>NFS (pour Network File System, système de fichiers en réseau) est un protocole qui permet à un ordinateur d’accéder à des fichiers via un réseau local.</em></p>
|
|||
|
|
|||
|
<h3 id="installation-nfs">Installation NFS</h3>
|
|||
|
|
|||
|
<p><img src="/images/nfs-new-logo.png" alt="" width="60" /></p>
|
|||
|
|
|||
|
<p>on passe en mode su<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo -s</code><br />
|
|||
|
Installation<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">apt install nfs-kernel-server</code><br />
|
|||
|
Vérification serveur<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">rpcinfo -p | grep nfs</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 100003 3 tcp 2049 nfs
|
|||
|
100003 4 tcp 2049 nfs
|
|||
|
100003 3 udp 2049 nfs
|
|||
|
100003 4 udp 2049 nfs
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier que le système supporte effectivement NFS<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">cat /proc/filesystems | grep nfs</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nodev nfsd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si la commande précédente ne renvoie rien, il se peut que le module NFS ne soit pas chargé, auquel cas, il faut le charger <code class="language-plaintext highlighter-rouge">modprobe nfs</code><br />
|
|||
|
Enfin, vérifions que portmap attend les instructions sur le port 111<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">rpcinfo -p | grep portmap</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 100000 4 tcp 111 portmapper
|
|||
|
100000 3 tcp 111 portmapper
|
|||
|
100000 2 tcp 111 portmapper
|
|||
|
100000 4 udp 111 portmapper
|
|||
|
100000 3 udp 111 portmapper
|
|||
|
100000 2 udp 111 portmapper
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="configuration-du-partage">Configuration du partage</h3>
|
|||
|
|
|||
|
<p>Espace disque</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df -h |grep "mapper"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev/mapper/svrxo--vg-root 28G 2,8G 24G 11% /
|
|||
|
/dev/mapper/svrxo--vg-home 75G 53M 71G 1% /home
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer un dossier data dans home</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir ~/{data,srv}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Passage en su<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo -s</code><br />
|
|||
|
indiquer au serveur les répertoires qui seront partagés, les machines qui y auront accès et les conditions de ce partage.<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">nano /etc/exports</code><br />
|
|||
|
Ajouter en fin de fichier <strong>/etc/exports</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Premier disque
|
|||
|
/home/xoadmin/data 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
/home/xoadmin/srv 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="sécurisation-nfs">Sécurisation NFS</h3>
|
|||
|
|
|||
|
<p>Passage en su<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo -s</code><br />
|
|||
|
Le protocole RPC n’a pas la réputation d’être bien sécurisé, mais la version 4 de NFS entend corriger ce problème, elle est donc à privilégier. Il est déconseillé d’effectuer un partage NFS via internet, ou bien dans ce cas, opter pour un tunnel crypté.</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>S’assurer que les partages sont réservés à certaines IP dans /etc/exports</li>
|
|||
|
<li>S’appuyer sur rpcbind (/etc/hosts.deny et /etc/hosts.allow) pour sécuriser l’accès au serveur NFS</li>
|
|||
|
<li>Configurer convenablement iptables</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><strong>hosts.deny , hosts.allow</strong><br />
|
|||
|
Tout le monde est interdit, puis le LAN est autorisé:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "rpcbind mountd nfsd statd lockd rquotad : ALL" >> /etc/hosts.deny
|
|||
|
echo "rpcbind mountd nfsd statd lockd rquotad: 192.168.0." >> /etc/hosts.allow
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>iptables (NFS)</strong><br />
|
|||
|
Par défaut, les différents services NFS (lockd, statd, mountd, etc.) demandent des assignations de ports aléatoires à partir du portmapper (portmap/rpcbind), ce qui signifie que la plupart des administrateurs doivent ouvrir une gamme de ports dans leur base de règles de pare-feu pour que NFS fonctionne.</p>
|
|||
|
|
|||
|
<p>Il va donc falloir fixer les ports de ces services afin de créer les règles iptables.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo 'STATDOPTS="--port 32765 --outgoing-port 32766"' >> /etc/default/nfs-common
|
|||
|
echo 'RPCMOUNTDOPTS="-p 32767"' >> /etc/default/nfs-kernel-server
|
|||
|
echo 'RPCRQUOTADOPTS="-p 32769"' >> /etc/default/quota
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relance sysctl<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sysctl --system</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>* Applying /etc/sysctl.d/99-sysctl.conf ...
|
|||
|
* Applying /etc/sysctl.conf ...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer le service<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">systemctl restart nfs-kernel-server</code></p>
|
|||
|
|
|||
|
<p>Nous pouvons maintenant fixer nos règles manuellement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>iptables -A INPUT -s 192.168.0.0/24 -p tcp -m multiport --ports 111,2049,32764:32769 -j ACCEPT -m comment --comment "NFS Server"
|
|||
|
iptables -A INPUT -s 192.168.0.0/24 -p udp -m multiport --ports 111,2049,32764:32769 -j ACCEPT -m comment --comment "NFS Server"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On sauve les règles</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>iptables-save > /etc/iptables/rules.v4
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="configuration-dun-client-nfs">Configuration d’un client NFS</h3>
|
|||
|
|
|||
|
<p>Prérequis : NFS installé (<a href="https://wiki.archlinux.fr/NFS">https://wiki.archlinux.fr/NFS</a>)</p>
|
|||
|
|
|||
|
<p>Visualiser les volumes accessibles<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">showmount -e 192.168.0.30</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Export list for 192.168.0.30:
|
|||
|
/home/xoadmin/data 192.168.0.0/24
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer un dossier pour le montage<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo mkdir /mnt/xoyaze</code><br />
|
|||
|
Donner les droits utilisateurs<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo chown $USER.users -R /mnt/xoyaze</code><br />
|
|||
|
Montage manuel<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo mount -t nfs4 -o rw 192.168.0.30:/home/xoadmin/data /mnt/xoyaze</code><br />
|
|||
|
Test lecture écriture<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">touch /mnt/xoyaze/test.txt</code> Ne doit générer aucune erreur <br />
|
|||
|
Montage auto , ajouter en fin de fichier <strong>/etc/fstab</strong><br />
|
|||
|
<code class="language-plaintext highlighter-rouge">192.168.0.30:/mnt/xoyaze /mnt/xoyaze nfs4 noauto,x-systemd.automount 0 0</code></p>
|
|||
|
|
|||
|
<p><strong>Client avec autofs</strong><br />
|
|||
|
Il suffit seulement de renseigner <strong>/etc/hosts</strong> avec la ligne suivante</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>192.168.0.30 srvxo
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ls -l /net/srvxo/home/xoadmin/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>total 0
|
|||
|
drwxr-xr-x 2 root root 0 6 mars 17:06 data
|
|||
|
drwxr-xr-x 2 root root 0 6 mars 17:06 srv
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="portail-xoyazxyz">Portail xoyaz.xyz</h2>
|
|||
|
|
|||
|
<p>Les fichiers html5 et autres sont dans le dossier <strong>/home/xoadmin/srv/default-www</strong></p>
|
|||
|
|
|||
|
<p><img src="/images/srvxo-srv.png" alt="" height="400" /></p>
|
|||
|
|
|||
|
<p>On va créer un lien avec le dossier par défaut du site</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm -r /var/www/default-www # on supprime le dossier existant
|
|||
|
sudo ln -s /home/xoadmin/srv/default-www /var/www/default-www # création du lien
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="test-vulnérabilité">Test vulnérabilité</h3>
|
|||
|
|
|||
|
<p><strong>Quality SSL Labs</strong> <a href="https://www.ssllabs.com/ssltest/analyze.html?d=xoyaz.xyz">https://www.ssllabs.com/ssltest/analyze.html?d=xoyaz.xyz</a><br />
|
|||
|
SSL Report: xoyaz.xyz<br />
|
|||
|
Assessed on: Thu, 07 Mar 2019 14:01:42 UTC</p>
|
|||
|
|
|||
|
<p><img src="/images/xoyaz.xyz-SSL-Labs.png" alt="image" width="400px" /></p>
|
|||
|
|
|||
|
<p><strong>Mozilla observatory</strong> <a href="https://observatory.mozilla.org/analyze.html?host=xoyaz.xyz">https://observatory.mozilla.org/analyze.html?host=xoyaz.xyz</a></p>
|
|||
|
|
|||
|
<p><img src="/images/mozilla-labs-xoyaz.xyz.png" alt="image" width="600px" /></p>
|
|||
|
|
|||
|
<p><a href="https://infosec.mozilla.org/guidelines/web_security#content-security-policy">Content Security Policy</a> -20 Content Security Policy (CSP) implemented unsafely.</p>
|
|||
|
|
|||
|
<h2 id="srvxo-xoyazxyz--ajout-de-3-disques-lvm">srvxo (xoyaz.xyz)- Ajout de 3 disques LVM</h2>
|
|||
|
|
|||
|
<p>/home/yannick/nas-one-yanplus/dplus/statique/images/crucial-ssd.png</p>
|
|||
|
|
|||
|
<p>Ajout de 3 disques LVM , SATA 3”5 4To et 2 SSD Crucial 512Go</p>
|
|||
|
|
|||
|
<p><img src="/images/disque-sata-logo.png" alt="" /> <img src="/images/crucial-ssd.png" alt="" width="100" /></p>
|
|||
|
|
|||
|
<p>Après mise en place physique des 3 éléments , on se connecte au serveur</p>
|
|||
|
|
|||
|
<p>les disques</p>
|
|||
|
|
|||
|
<p>Les disques LVM</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
pvs
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvs
|
|||
|
|
|||
|
PV VG Fmt Attr PSize PFree
|
|||
|
/dev/sda5 svrxo-vg lvm2 a-- 111,55g 0
|
|||
|
/dev/sdb3 vg-nas-one lvm2 a-- 3,64t 677,72g
|
|||
|
/dev/sdc1 vg-ssd-two lvm2 a-- 111,79g 0
|
|||
|
/dev/sdd3 vg-ssd-one lvm2 a-- 446,85g 142,85g
|
|||
|
|
|||
|
vgs
|
|||
|
|
|||
|
VG #PV #LV #SN Attr VSize VFree
|
|||
|
svrxo-vg 1 3 0 wz--n- 111,55g 0
|
|||
|
vg-nas-one 1 3 0 wz--n- 3,64t 677,72g
|
|||
|
vg-ssd-one 1 5 0 wz--n- 446,85g 142,85g
|
|||
|
vg-ssd-two 1 1 0 wz--n- 111,79g 0
|
|||
|
|
|||
|
lvs
|
|||
|
|
|||
|
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
|
|||
|
home svrxo-vg -wi-ao---- 76,18g
|
|||
|
root svrxo-vg -wi-ao---- 27,94g
|
|||
|
swap_1 svrxo-vg -wi-ao---- 7,43g
|
|||
|
sav vg-nas-one -wi-a----- 500,00g
|
|||
|
video vg-nas-one -wi-a----- 2,00t
|
|||
|
yanplus vg-nas-one -wi-a----- 500,00g
|
|||
|
data vg-ssd-one -wi-a----- 100,00g
|
|||
|
home vg-ssd-one -wi-a----- 75,00g
|
|||
|
musique vg-ssd-one -wi-a----- 100,00g
|
|||
|
root vg-ssd-one -wi-a----- 25,00g
|
|||
|
swap vg-ssd-one -wi-a----- 4,00g
|
|||
|
lv-ssd-two vg-ssd-two -wi-a----- 111,79g
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les UUID</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>blkid
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev/sda1: UUID="0b3181c7-e410-4b18-9611-c809fedbeb3c" TYPE="ext2" PARTUUID="8f806fa7-01"
|
|||
|
/dev/sda5: UUID="ooWgEh-AHL4-naPs-s2eN-dw4T-Yuxx-ak42Lb" TYPE="LVM2_member" PARTUUID="8f806fa7-05"
|
|||
|
/dev/sdb1: PARTLABEL="BIOS boot partition" PARTUUID="ed937de2-0476-4053-b61d-2762f585b06e"
|
|||
|
/dev/sdb3: UUID="nLFric-2HkM-T6TB-u6Hk-svmd-qgcw-3jaNUq" TYPE="LVM2_member" PARTLABEL="Linux LVM" PARTUUID="14c9fbd9-577a-437c-a51b-bc15e3910883"
|
|||
|
/dev/sdc1: UUID="Yiq13W-7Y74-se09-6RUp-Olo5-4vxi-y5lBk8" TYPE="LVM2_member" PARTUUID="ad94cf63-01"
|
|||
|
/dev/sdd1: PARTLABEL="BIOS boot partition" PARTUUID="b14e299d-a261-41c2-87cb-3a94bb8d2ca9"
|
|||
|
/dev/sdd2: UUID="884d7a9a-0022-4327-8b5c-122fdaa395bb" TYPE="ext2" PARTLABEL="boot" PARTUUID="bef1c7c4-5e4d-4abe-8110-1b281eec3d30"
|
|||
|
/dev/sdd3: UUID="Iibu0Y-HfOC-zZlp-Laby-27z9-djFq-asxVR1" TYPE="LVM2_member" PARTLABEL="Linux LVM" PARTUUID="d7fa9f3a-36cb-4603-836b-a5175d0ebd9a"
|
|||
|
/dev/mapper/vg--ssd--one-root: LABEL="root" UUID="a9676b49-3225-42cd-aba9-0ce41d68b82d" TYPE="ext4"
|
|||
|
/dev/mapper/vg--ssd--one-swap: UUID="a38e2362-224b-4f33-8931-6cd09bbaa4d8" TYPE="swap"
|
|||
|
/dev/mapper/vg--ssd--one-home: UUID="c15f4528-6bee-4f4d-9522-61389a697d83" TYPE="ext4"
|
|||
|
/dev/mapper/vg--ssd--one-data: LABEL="data" UUID="a6d46937-e8a3-4e90-a1a6-919d219ed7c1" TYPE="ext4"
|
|||
|
/dev/mapper/vg--ssd--one-musique: UUID="9a7302c4-6c70-46bd-836c-cea53d499f33" TYPE="ext4"
|
|||
|
/dev/mapper/vg--ssd--two-lv--ssd--two: UUID="92a2a93e-3858-42e9-bafa-9599b6dfa825" TYPE="ext4"
|
|||
|
/dev/mapper/vg--nas--one-yanplus: UUID="c6ab468e-ed7b-491e-b7c3-010a70816d0c" TYPE="ext4"
|
|||
|
/dev/mapper/vg--nas--one-video: UUID="e2f56559-c05c-4fe9-8344-cbe06059bf90" TYPE="ext4"
|
|||
|
/dev/mapper/vg--nas--one-sav: UUID="894e79a6-d542-45e0-8b71-3b156ddce0e6" TYPE="ext4"
|
|||
|
/dev/mapper/svrxo--vg-root: UUID="8270a496-9bda-4937-8964-07d03da5d84e" TYPE="ext4"
|
|||
|
/dev/mapper/svrxo--vg-swap_1: UUID="fd5aa6ed-c9c4-4209-b307-1e9d853250c7" TYPE="swap"
|
|||
|
/dev/mapper/svrxo--vg-home: UUID="a24877fc-f1e6-4a22-8c65-c62ccef514d8" TYPE="ext4"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les points de montage , création des dossiers et du fstab</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir -p /srv/{nas-one-sav,nas-one-video,nas-one-yanplus,ssd-one-home,ssd-one-musique,ssd-one-root,ssd-two-lv}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier fstab</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/fstab
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># /etc/fstab: static file system information.
|
|||
|
#
|
|||
|
# Use 'blkid' to print the universally unique identifier for a
|
|||
|
# device; this may be used with UUID= as a more robust way to name devices
|
|||
|
# that works even if disks are added and removed. See fstab(5).
|
|||
|
#
|
|||
|
# <file system> <mount point> <type> <options> <dump> <pass>
|
|||
|
/dev/mapper/svrxo--vg-root / ext4 errors=remount-ro 0 1
|
|||
|
# /boot was on /dev/sda1 during installation
|
|||
|
UUID=0b3181c7-e410-4b18-9611-c809fedbeb3c /boot ext2 defaults 0 2
|
|||
|
/dev/mapper/svrxo--vg-home /home ext4 defaults 0 2
|
|||
|
/dev/mapper/svrxo--vg-swap_1 none swap sw 0 0
|
|||
|
|
|||
|
# SSD NAS
|
|||
|
/dev/mapper/vg--nas--one-sav /srv/nas-one-sav ext4 defaults 0 2
|
|||
|
/dev/mapper/vg--nas--one-video /srv/nas-one-video ext4 defaults 0 2
|
|||
|
/dev/mapper/vg--nas--one-yanplus /srv/nas-one-yanplus ext4 defaults 0 2
|
|||
|
/dev/mapper/vg--ssd--one-home /srv/ssd-one-home ext4 defaults 0 2
|
|||
|
/dev/mapper/vg--ssd--one-data /srv/ssd-one-data ext4 defaults 0 2
|
|||
|
/dev/mapper/vg--ssd--one-musique /srv/ssd-one-musique ext4 defaults 0 2
|
|||
|
/dev/mapper/vg--ssd--one-root /srv/ssd-one-root ext4 defaults 0 2
|
|||
|
/dev/mapper/vg--ssd--two-lv--ssd--two /srv/ssd-two-lv ext4 defaults 0 2
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="srvxo---nfs">srvxo - NFS</h3>
|
|||
|
|
|||
|
<p><img src="/images/nfs-new-logo.png" alt="" /></p>
|
|||
|
|
|||
|
<p>NFS exports exportfs -arv</p>
|
|||
|
|
|||
|
<p>Modifier le fichier <strong>/etc/exports</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># /etc/exports: the access control list for filesystems which may be exported
|
|||
|
# to NFS clients. See exports(5).
|
|||
|
#
|
|||
|
# Example for NFSv2 and NFSv3:
|
|||
|
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
|
|||
|
#
|
|||
|
# Example for NFSv4:
|
|||
|
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
|
|||
|
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
|
|||
|
#
|
|||
|
# Premier disque
|
|||
|
/home/xoadmin/data 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
/home/xoadmin/srv 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
|
|||
|
# SSD NAS
|
|||
|
/srv/nas-one-yanplus 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
/srv/nas-one-video 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
/srv/ssd-one-musique 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
/srv/ssd-one-data 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
/srv/ssd-two-lv 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Prise en charge</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>exportfs -arv
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>exporting 192.168.0.0/24:/srv/ssd-two-lv
|
|||
|
exporting 192.168.0.0/24:/srv/ssd-one-data
|
|||
|
exporting 192.168.0.0/24:/srv/ssd-one-musique
|
|||
|
exporting 192.168.0.0/24:/srv/nas-one-video
|
|||
|
exporting 192.168.0.0/24:/srv/nas-one-yanplus
|
|||
|
exporting 192.168.0.0/24:/home/xoadmin/srv
|
|||
|
exporting 192.168.0.0/24:/home/xoadmin/data
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="borgbackup">BorgBackup</h2>
|
|||
|
|
|||
|
<p><img src="/images/borg-logo.png" alt="" /></p>
|
|||
|
|
|||
|
<h3 id="installation">Installation</h3>
|
|||
|
|
|||
|
<p>Debian Stretch avec les dépôts “backports”</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt edit-sources # pour ajouter la ligne pour les dépôts "backports"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>deb http://deb.debian.org/debian stretch-backports main contrib non-free
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Votre fichier « /etc/apt/sources.list » a changé, veuillez lancer « apt-get update »</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt update
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer borgbackup</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt -V -t=stretch-backports install borgbackup
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="préparation-de-la-machine-qui-stocke-les-sauvegardes-srvxo-xoyazxyz">Préparation de la machine qui stocke les sauvegardes srvxo (xoyaz.xyz)</h3>
|
|||
|
|
|||
|
<p>Le dossier de base pour les sauvegardes sur le serveur srvxo (xoyaz.xyz) : <strong>/srv/ssd-two-lv/borg-backups/</strong></p>
|
|||
|
|
|||
|
<p>En mode su<br />
|
|||
|
Commencer par installer Borg (Installation sur Debian Stretch avec les dépôts “backports”) et openssh-server si ça n’est pas déjà le cas.</p>
|
|||
|
|
|||
|
<p>Il est préférable de créer un utilisateur dédié aux sauvegardes :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useradd borg --create-home --home-dir /srv/ssd-two-lv/borg-backups/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vous pouvez changer /srv/ssd-two-lv/borg-backups pour n’importe quel emplacement où vous êtes susceptible d’avoir suffisamment d’espace disque.</p>
|
|||
|
|
|||
|
<h4 id="comment-ajouter-une-clé-publique-sur-la-machine-qui-stocke-les-sauvegardes-srvxo-xoyazxyz">Comment ajouter une clé publique sur la machine qui stocke les sauvegardes srvxo (xoyaz.xyz)</h4>
|
|||
|
|
|||
|
<p>Se connecter sur la machine xoyize.xyz en ssh et ajouter de la clé publique</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
mkdir -p /srv/ssd-two/borg-backups/.ssh # sans incidence si répertoire existe déjà
|
|||
|
cat >> /srv/ssd-two/borg-backups/.ssh/authorized_keys
|
|||
|
|
|||
|
Copier/coller le contenu du fichier du fichier de clef publique (fichier /root/.ssh/client.pub de la machine à sauvegarder ) dans ce terminal, et presser [Ctrl]+[D] pour valider.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour info, les clefs publiques clientes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat /srv/ssd-two-lv/borg-backups/.ssh/authorized_keys
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAqJxvGRot7fEnh+dtKvy4EORwKXqGbloxM6hldnANpH root@yanspm.com
|
|||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL1VZR9M0Al47ACqg3HZM3UCQ2tWF/7H/eFD+lsDasyN root@yanfi.net
|
|||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKTVAK9iElmsM/bbw5VvVI7rR4GF6It/WjJnuHMYqUdk root@cinay.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="machines-clientes---exécution-sauvegarde">Machines clientes - Exécution sauvegarde</h3>
|
|||
|
|
|||
|
<h4 id="suite-changement-du-serveur-des-dépôts">Suite changement du serveur des dépôts</h4>
|
|||
|
|
|||
|
<p>Modifier les fichiers <strong>/root/.borg/borg-backup</strong> de chaque client , pour prendre en compte le nouveau serveur <strong>xoyaz.xyz</strong>.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BORG_REPOSITORY=ssh://borg@xoyaz.xyz:55034/srv/ssd-two-lv/borg-backups/Nom_DEPOT
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Exécuter manuellement pour valider le changement de lieu du dépôt</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/root/.borg/borg-backup
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set -e
|
|||
|
|
|||
|
BACKUP_DATE=`date +%Y-%m-%d-%Hh%M`
|
|||
|
LOG_PATH=/var/log/borg-backup.log
|
|||
|
|
|||
|
export BORG_PASSPHRASE="`cat ~root/.borg/passphrase`"
|
|||
|
export BORG_RSH='ssh -i /root/.ssh/yanfi_ed25519'
|
|||
|
BORG_REPOSITORY=ssh://borg@xoyaz.xyz:55034/srv/ssd-two-lv/borg-backups/yanfi.net
|
|||
|
BORG_ARCHIVE=${BORG_REPOSITORY}::${BACKUP_DATE}
|
|||
|
|
|||
|
borg create \
|
|||
|
-v --stats --compression lzma,9 \
|
|||
|
$BORG_ARCHIVE \
|
|||
|
/bin /boot /etc /home /lib /lib64 /opt /root /sbin /srv /usr /var
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>puis</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>borg prune \
|
|||
|
-v --list --stats --keep-daily=7 --keep-weekly=4 --keep-monthly=6 \
|
|||
|
$BORG_REPOSITORY
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>En cas d’erreur du type <code class="language-plaintext highlighter-rouge">Borg: Failed to create/acquire the lock /lock.exclusive (timeout).</code><br />
|
|||
|
Exécuter la commande suivante <code class="language-plaintext highlighter-rouge">borg break-lock $BORG_REPOSITORY</code></p>
|
|||
|
|
|||
|
<h2 id="nextcloud">Nextcloud</h2>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud_logo.png" alt="nextcloud" /></p>
|
|||
|
|
|||
|
<p>On passe en mode super utilisateur<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo -s</code></p>
|
|||
|
|
|||
|
<h3 id="base-mysql-nextcloud">Base mysql nextcloud</h3>
|
|||
|
|
|||
|
<p>Créer une base mariadb Nextcloud<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">mysql -uadmin -p$(cat /etc/mysql/mdp)</code><br />
|
|||
|
sur le prompt <strong>MariaDB [(none)]></strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CREATE DATABASE nextcloud;
|
|||
|
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost' IDENTIFIED BY 'mot-de-passe-base-nextcloud';
|
|||
|
FLUSH PRIVILEGES;
|
|||
|
quit
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="installer-nextcloud">Installer nextcloud</h3>
|
|||
|
|
|||
|
<p>Télécharger la denière version de <strong>nextcloud</strong> (<a href="https://download.nextcloud.com/server/releases/">https://download.nextcloud.com/server/releases/</a>) <br />
|
|||
|
<code class="language-plaintext highlighter-rouge">wget https://download.nextcloud.com/server/releases/nextcloud-15.0.5.zip</code> <br />
|
|||
|
Extraction après téléchargement du fichier<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">unzip nextcloud-15.0.5.zip</code><br />
|
|||
|
Déplacer le dossier extrait vers le répertoire web <strong>/var/www/</strong><br />
|
|||
|
<code class="language-plaintext highlighter-rouge">mv nextcloud /var/www/</code><br />
|
|||
|
Effacer le zip<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">rm nextcloud-15.0.5.zip</code><br />
|
|||
|
Créer le dossier <strong>data</strong><br />
|
|||
|
<code class="language-plaintext highlighter-rouge">mkdir /var/www/nextcloud/data</code></p>
|
|||
|
|
|||
|
<p>Modifiez le propriétaire et le groupe du répertoire /var/www/nextcloud :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">chown -R www-data:www-data /var/www/nextcloud/</code><br />
|
|||
|
Modifier les droits<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">find /var/www/nextcloud/ -type d -exec chmod 750 {} \;</code><br />
|
|||
|
<code class="language-plaintext highlighter-rouge">find /var/www/nextcloud/ -type f -exec chmod 640 {} \;</code></p>
|
|||
|
|
|||
|
<p>Le pool dédié à Nextcloud <strong>/etc/php/7.3/fpm/pool.d/nextcloud.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[nextcloud]
|
|||
|
|
|||
|
listen = /run/php/php7.3-fpm-nextcloud.sock
|
|||
|
|
|||
|
; Set permissions for unix socket, if one is used.Méthoe B listen.owner = nextcloud
|
|||
|
listen.owner = www-data
|
|||
|
listen.group = www-data
|
|||
|
listen.mode = 0660
|
|||
|
|
|||
|
; Unix user/group of processes. user = nextcloud (méthode B)
|
|||
|
user = www-data
|
|||
|
group = www-data
|
|||
|
|
|||
|
pm = dynamic
|
|||
|
pm.max_children = 6
|
|||
|
pm.start_servers = 3
|
|||
|
pm.min_spare_servers = 3
|
|||
|
pm.max_spare_servers = 5
|
|||
|
pm.max_requests = 500
|
|||
|
pm.status_path = /fpm-status
|
|||
|
ping.path = /ping
|
|||
|
request_terminate_timeout = 1d
|
|||
|
request_slowlog_timeout = 5s
|
|||
|
slowlog = /var/log/nginx/nextcloud.slow.log
|
|||
|
rlimit_files = 4096
|
|||
|
rlimit_core = 0
|
|||
|
chdir = /var/www/nextcloud/
|
|||
|
catch_workers_output = yes
|
|||
|
clear_env = no
|
|||
|
|
|||
|
php_value[upload_max_filesize] = 10G
|
|||
|
php_value[post_max_size] = 10G
|
|||
|
php_value[default_charset] = UTF-8
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrez le service php-fpm afin d’activer le nouveau pool nextcloud :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo systemctl restart php7.3-fpm.service</code></p>
|
|||
|
|
|||
|
<p>Nginx virtualhost</p>
|
|||
|
|
|||
|
<p>Le fichier de configuration nginx <strong>/etc/nginx/conf.d/nextcloud.xoyaz.xyz.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>upstream php-handler {
|
|||
|
#server 127.0.0.1:9000;
|
|||
|
server unix:/run/php/php7.3-fpm-nextcloud.sock;
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 80;
|
|||
|
listen [::]:80;
|
|||
|
server_name nextcloud.xoyaz.xyz;
|
|||
|
# enforce https
|
|||
|
return 301 https://$server_name$request_uri;
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 443 ssl http2;
|
|||
|
listen [::]:443 ssl http2;
|
|||
|
server_name nextcloud.xoyaz.xyz;
|
|||
|
|
|||
|
ssl_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
|
|||
|
ssl_certificate_key /etc/ssl/private/xoyaz.xyz-key.pem;
|
|||
|
ssl_session_timeout 5m;
|
|||
|
ssl_session_cache shared:SSL:50m;
|
|||
|
|
|||
|
# As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519
|
|||
|
# (this doesn't work on jessie though ...?)
|
|||
|
# ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
|
|||
|
|
|||
|
# As suggested by https://cipherli.st/
|
|||
|
ssl_ecdh_curve secp384r1;
|
|||
|
|
|||
|
ssl_prefer_server_ciphers on;
|
|||
|
|
|||
|
# Ciphers with modern compatibility
|
|||
|
#---------------------------------
|
|||
|
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern
|
|||
|
# Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...)
|
|||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|||
|
ssl_ciphers 'TLS13+AESGCM+AES128:EECDH+AESGCM:EECDH+CHACHA20:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
|
|||
|
|
|||
|
# Add headers to serve security related headers
|
|||
|
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
|
|||
|
add_header X-Content-Type-Options nosniff;
|
|||
|
add_header X-XSS-Protection "1; mode=block";
|
|||
|
add_header X-Robots-Tag none;
|
|||
|
add_header X-Download-Options noopen;
|
|||
|
add_header X-Permitted-Cross-Domain-Policies none;
|
|||
|
add_header Referrer-Policy no-referrer;
|
|||
|
|
|||
|
# Remove X-Powered-By, which is an information leak
|
|||
|
fastcgi_hide_header X-Powered-By;
|
|||
|
|
|||
|
# Path to the root of your installation
|
|||
|
root /var/www/nextcloud/;
|
|||
|
|
|||
|
location = /robots.txt {
|
|||
|
allow all;
|
|||
|
log_not_found off;
|
|||
|
access_log off;
|
|||
|
}
|
|||
|
|
|||
|
# The following 2 rules are only needed for the user_webfinger app.
|
|||
|
# Uncomment it if you're planning to use this app.
|
|||
|
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
|
|||
|
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
|
|||
|
|
|||
|
location = /.well-known/carddav {
|
|||
|
return 301 $scheme://$host/remote.php/dav;
|
|||
|
}
|
|||
|
location = /.well-known/caldav {
|
|||
|
return 301 $scheme://$host/remote.php/dav;
|
|||
|
}
|
|||
|
|
|||
|
# set max upload size
|
|||
|
client_max_body_size 512M;
|
|||
|
fastcgi_buffers 64 4K;
|
|||
|
|
|||
|
# Enable gzip but do not remove ETag headers
|
|||
|
gzip on;
|
|||
|
gzip_vary on;
|
|||
|
gzip_comp_level 4;
|
|||
|
gzip_min_length 256;
|
|||
|
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
|||
|
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
|||
|
|
|||
|
# Uncomment if your server is build with the ngx_pagespeed module
|
|||
|
# This module is currently not supported.
|
|||
|
#pagespeed off;
|
|||
|
|
|||
|
location / {
|
|||
|
rewrite ^ /index.php$request_uri;
|
|||
|
}
|
|||
|
|
|||
|
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
|
|||
|
deny all;
|
|||
|
}
|
|||
|
|
|||
|
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+)\.php(?:$|\/) {
|
|||
|
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
|
|||
|
include fastcgi_params;
|
|||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|||
|
fastcgi_param HTTPS on;
|
|||
|
#Avoid sending the security headers twice
|
|||
|
fastcgi_param modHeadersAvailable true;
|
|||
|
fastcgi_param front_controller_active true;
|
|||
|
fastcgi_pass php-handler;
|
|||
|
fastcgi_intercept_errors on;
|
|||
|
fastcgi_request_buffering off;
|
|||
|
}
|
|||
|
|
|||
|
location ~ ^\/(?:updater|ocs-provider)(?:$|\/) {
|
|||
|
try_files $uri/ =404;
|
|||
|
index index.php;
|
|||
|
}
|
|||
|
|
|||
|
# Adding the cache control header for js and css files
|
|||
|
# Make sure it is BELOW the PHP block
|
|||
|
location ~ \.(?:css|js|woff2?|svg|gif)$ {
|
|||
|
try_files $uri /index.php$request_uri;
|
|||
|
add_header Cache-Control "public, max-age=15778463";
|
|||
|
# Add headers to serve security related headers (It is intended to
|
|||
|
# have those duplicated to the ones above)
|
|||
|
# Before enabling Strict-Transport-Security headers please read into
|
|||
|
# this topic first.
|
|||
|
# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
|
|||
|
#
|
|||
|
# WARNING: Only add the preload option once you read about
|
|||
|
# the consequences in https://hstspreload.org/. This option
|
|||
|
# will add the domain to a hardcoded list that is shipped
|
|||
|
# in all major browsers and getting removed from this list
|
|||
|
# could take several months.
|
|||
|
add_header X-Content-Type-Options nosniff;
|
|||
|
add_header X-XSS-Protection "1; mode=block";
|
|||
|
add_header X-Robots-Tag none;
|
|||
|
add_header X-Download-Options noopen;
|
|||
|
add_header X-Permitted-Cross-Domain-Policies none;
|
|||
|
add_header Referrer-Policy no-referrer;
|
|||
|
|
|||
|
# Optional: Don't log access to assets
|
|||
|
access_log off;
|
|||
|
}
|
|||
|
|
|||
|
location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
|
|||
|
try_files $uri /index.php$request_uri;
|
|||
|
# Optional: Don't log access to other assets
|
|||
|
access_log off;
|
|||
|
}
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier nginx<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">nginx -t</code><br />
|
|||
|
Relancer php-fpm et nginx<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">systemctl restart php7.3-fpm nginx</code></p>
|
|||
|
|
|||
|
<h3 id="initialisation-nextcloud">Initialisation nextcloud</h3>
|
|||
|
|
|||
|
<p>Accès https://nextcloud.xoyaz.xyz<br />
|
|||
|
Créer un compte administrateur yanspm + mot de passe<br />
|
|||
|
Répertoire des données /var/www/nextcloud/data<br />
|
|||
|
Base MariaDb (MySql) nextcloud , utilisateur nextcloud + mot de passe accès</p>
|
|||
|
|
|||
|
<p>Aller dans Paramètres → Vue d’ensemble</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Avertissements de sécurité & configuration
|
|||
|
|
|||
|
Il est important pour la sécurité et la performance de votre instance que celle-ci soit correctement configurée. Afin de vous aider, votre instance Nextcloud effectue quelques vérifications automatiques. Pour de plus amples informations, veuillez consulter la documentation liée.
|
|||
|
Il y a quelques avertissements concernant votre configuration.
|
|||
|
|
|||
|
Aucun cache mémoire n'est configuré. Si possible, configurez un "memcache" pour améliorer les performances. Pour plus d'informations consultez la documentation.
|
|||
|
Le PHP OPcache n'est pas correctement configuré. Pour de meilleure performance nous recommandons d'utiliser les paramètres suivant dans le php.ini :
|
|||
|
|
|||
|
opcache.enable=1
|
|||
|
opcache.enable_cli=1
|
|||
|
opcache.interned_strings_buffer=8
|
|||
|
opcache.max_accelerated_files=10000
|
|||
|
opcache.memory_consumption=128
|
|||
|
opcache.save_comments=1
|
|||
|
opcache.revalidate_freq=1
|
|||
|
|
|||
|
Certaines colonnes de la base de données n'ont pas été converties en big int. Changer le type de colonne dans de grandes tables peu prendre beaucoup de temps, elles n'ont donc pas été converties automatiquement. En exécutant 'occ db:convert-filecache-bigint' ces changements en suspens peuvent être déclenchés manuellement. Cette opération doit être exécutée pendant que l'instance est hors ligne. Pour plus d'information, consulter la page de la documentation.
|
|||
|
filecache.mtime
|
|||
|
filecache.storage_mtime
|
|||
|
|
|||
|
Merci de consulter les guides d'installation ↗ et de vérifier les erreurs ou avertissements des logs.
|
|||
|
|
|||
|
Vérifier la sécurité de votre Nextcloud grâce à notre scan de sécurité ↗
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="les-corrections">Les corrections</h3>
|
|||
|
|
|||
|
<h4 id="cache-php--opcache">Cache PHP : OPcache</h4>
|
|||
|
|
|||
|
<p><em>OPcache (qui signifie Optimizer Plus Cache) est introduit depuis la version 5.5.0 de PHP. Il sert à cacher l’opcode de PHP, c’est-à-dire les instructions de bas niveau générées par la machine virtuelle PHP lors de l’exécution d’un script. Autrement dit, le code pré-compilé est stocké en mémoire. Cela évite ainsi l’étape de compilation à chaque requête PHP. De plus, OPcache va optimiser l’exécution du code afin d’en améliorer les performances.</em></p>
|
|||
|
|
|||
|
<p>Éditez le fichier /etc/php/7.3/fpm/php.ini, décommentez et modifiez les lignes suivantes dans la section [opcache] :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo nano /etc/php/7.3/fpm/php.ini</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[opcache]
|
|||
|
opcache.enable=1
|
|||
|
opcache.enable_cli=1
|
|||
|
opcache.interned_strings_buffer=8
|
|||
|
opcache.max_accelerated_files=10000
|
|||
|
opcache.memory_consumption=128
|
|||
|
opcache.save_comments=1
|
|||
|
opcache.revalidate_freq=1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>La nouvelle configuration sera prise en compte après redémarrage du service PHP-FPM :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo systemctl restart php7.3-fpm.service</code></p>
|
|||
|
|
|||
|
<h4 id="cache-de-données--apcu--redis">Cache de données : APCu & Redis</h4>
|
|||
|
|
|||
|
<p><em>APCu permet notamment de mettre en cache les variables PHP et de les stocker en mémoire vive. Redis est un système de gestion de base de données NoSQL avec un système de clef-valeur scalable (s’adapte à la charge). Une des principales caractéristiques de Redis est de conserver l’intégralité des données en RAM. Cela permet d’obtenir d’excellentes performances en évitant les accès disques, particulièrement coûteux.</em></p>
|
|||
|
|
|||
|
<p>Installez les paquets APCu et Redis :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo apt install php-apcu redis-server php-redis -y</code><br />
|
|||
|
Ajoutez les lignes suivantes dans le fichier <strong>/var/www/nextcloud/config/config.php</strong> :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo nano /var/www/nextcloud/config/config.php</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 'memcache.local' => '\OC\Memcache\APCu',
|
|||
|
'memcache.distributed' => '\OC\Memcache\Redis',
|
|||
|
'memcache.locking' => '\OC\Memcache\Redis',
|
|||
|
'redis' => [
|
|||
|
'host' => 'localhost',
|
|||
|
'port' => 6379,
|
|||
|
],
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>La nouvelle configuration sera prise en compte après redémarrage du service PHP-FPM :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo systemctl restart php7.3-fpm.service</code></p>
|
|||
|
|
|||
|
<h4 id="correction-anomalie-big-int">Correction anomalie Big Int</h4>
|
|||
|
|
|||
|
<p>Message du type: <em>Certaines colonnes de la base de données n’ont pas été converties en BigInt (64 bits). Changer le type de colonne dans de grandes tables peu prendre beaucoup de temps, elles n’ont donc pas été converties automatiquement. En exécutant ‘occ db:convert-filecache-bigint’ ces changements en suspens peuvent être déclenchés manuellement. Cette opération doit être exécutée pendant que l’instance est hors ligne.</em></p>
|
|||
|
|
|||
|
<p>Depuis Nextcloud 13 les BigInt sont utilisés pour stocker les identifiants et les clés auto-incrément dans la base de données. Comme le changement de colonnes sur de grandes tables peut prendre un certain temps (jusqu’à plusieurs heures ou jours), la mise à jour de Nextcloud 12 ou plus tôt n’a pas effectué cette migration sur le cache de fichiers et la table d’activité.</p>
|
|||
|
|
|||
|
<p>Pour faciliter la mise à jour de ces tables, nous avons ajouté une commande console, qui peut être utilisée pour migrer les colonnes restantes vers bigints.</p>
|
|||
|
|
|||
|
<p>La commande peut être exécutée en toute sécurité.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
cd /var/www/nextcloud/
|
|||
|
$ sudo -u www-data php occ db:convert-filecache-bigint
|
|||
|
Following columns will be updated:
|
|||
|
|
|||
|
* filecache.mtime
|
|||
|
* filecache.storage_mtime
|
|||
|
|
|||
|
This can take up to hours, depending on the number of files in your instance!
|
|||
|
Continue with the conversion (y/n)? [n] y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Au second passage, il affichera un message</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo -u www-data php occ db:convert-filecache-bigint
|
|||
|
|
|||
|
All tables already up to date!
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Note : Comme pour une mise à jour normale, vous devriez fermer votre serveur apache ou nginx ou activer le mode maintenance avant d’exécuter la commande pour éviter les problèmes avec vos clients de synchronisation.</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3 id="vérification-nextcloud">Vérification nextcloud</h3>
|
|||
|
|
|||
|
<p>On se connecte sur nextcloud , Paramètres → Vue d’ensemble</p>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud-security.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<p>On lance le <a href="https://scan.nextcloud.com/">scan de sécurité nextcloud</a></p>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud-security-1.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<h2 id="développement">Développement</h2>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ____ _ _
|
|||
|
| _ \ _____ _____| | ___ _ __ _ __ ___ ___ _ __ | |_
|
|||
|
| | | |/ _ \ \ / / _ \ |/ _ \| '_ \| '_ ` _ \ / _ \ '_ \| __|
|
|||
|
| |_| | __/\ V / __/ | (_) | |_) | | | | | | __/ | | | |_
|
|||
|
|____/ \___| \_/ \___|_|\___/| .__/|_| |_| |_|\___|_| |_|\__|
|
|||
|
|_|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>devel <strong>/etc/nginx/conf.d/devel.devel.xoyaz.xyz.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
|
|||
|
listen 80;
|
|||
|
listen [::]:80;
|
|||
|
|
|||
|
## redirect http to https ##
|
|||
|
server_name devel.xoyaz.xyz;
|
|||
|
return 301 https://$server_name$request_uri;
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 443 ssl http2;
|
|||
|
listen [::]:443 ssl http2;
|
|||
|
server_name devel.xoyaz.xyz;
|
|||
|
|
|||
|
#### Locations
|
|||
|
# On cache les fichiers statiques
|
|||
|
location ~* \.(html|css|js|png|jpg|jpeg|gif|ico|svg|eot|woff|ttf)$ { expires max; }
|
|||
|
# On interdit les dotfiles
|
|||
|
location ~ /\. { deny all; }
|
|||
|
|
|||
|
include ssl_params;
|
|||
|
include header_params;
|
|||
|
# Diffie-Hellmann
|
|||
|
# Uncomment the following directive after DH generation
|
|||
|
# > openssl dhparam -out /etc/ssl/private/dh4096.pem -outform PEM -2 4096
|
|||
|
# ssl_dhparam /etc/ssl/private/dh4096.pem;
|
|||
|
|
|||
|
# autoindex on;
|
|||
|
fancyindex on; # Enable fancy indexes.
|
|||
|
fancyindex_exact_size off; # Output human-readable file sizes.
|
|||
|
|
|||
|
root /srv/nas-one-yanplus/devel/ouestline/ ;
|
|||
|
index index.php index.html index.htm;
|
|||
|
location ~ \.php$ {
|
|||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|||
|
fastcgi_pass unix:/run/php/php7.3-fpm.sock; # PHP7.3
|
|||
|
fastcgi_index index.php;
|
|||
|
include fastcgi_params;
|
|||
|
fastcgi_param SCRIPT_FILENAME $request_filename;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
access_log /var/log/nginx/devel.xoyaz.xyz-access.log;
|
|||
|
error_log /var/log/nginx/devel.xoyaz.xyz-error.log;
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérification et relance nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
|
|||
|
sudo systemctl restart nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="subsonic">Subsonic</h2>
|
|||
|
|
|||
|
<p><img src="/images/subsonic-logo.png" alt="Subsonic" /></p>
|
|||
|
|
|||
|
<p><em>Application dédiée musique, serveur java</em></p>
|
|||
|
|
|||
|
<p>Dossier /srv/musique (musique vg-ssd-one -wi-ao—- 100,00g)<br />
|
|||
|
Installer java <br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo apt install openjdk-8-jre</code><br />
|
|||
|
Installer subsonic , télécharger la version en cours<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">wget https://s3-eu-west-1.amazonaws.com/subsonic-public/download/subsonic-6.1.5.deb # paquet deb subsonic</code><br />
|
|||
|
Installer<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo dpkg -i subsonic-6.1.5.deb</code><br />
|
|||
|
Modifier le paramètrage <strong>/etc/default/subsonic</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SUBSONIC_ARGS="--host=192.168.0.30 --port=8090 --max-memory=200"
|
|||
|
SUBSONIC_USER=xoadmin
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer subsonic<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo systemctl restart subsonic</code></p>
|
|||
|
|
|||
|
<p>Virtual host <strong>/etc/nginx/conf.d/music.xoyaz.xyz.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>upstream subsonic {
|
|||
|
server 192.168.0.30:8090;
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 80;
|
|||
|
listen [::]:80;
|
|||
|
|
|||
|
## redirect http to https ##
|
|||
|
server_name music.xoyaz.xyz;
|
|||
|
return 301 https://$server_name$request_uri;
|
|||
|
}
|
|||
|
|
|||
|
server {
|
|||
|
listen 443 ssl http2;
|
|||
|
listen [::]:443 ssl http2;
|
|||
|
server_name music.xoyaz.xyz;
|
|||
|
|
|||
|
include ssl_params;
|
|||
|
include header_params;
|
|||
|
|
|||
|
location / {
|
|||
|
|
|||
|
proxy_set_header X-Real-IP $remote_addr;
|
|||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|||
|
proxy_redirect off;
|
|||
|
proxy_set_header Host $http_host;
|
|||
|
proxy_pass http://subsonic;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
access_log /var/log/nginx/music.xoyaz.xyz-access.log;
|
|||
|
error_log /var/log/nginx/music.xoyaz.xyz-error.log;
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérification et relance nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
|
|||
|
sudo systemctl restart nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le dossier musique : <strong>/srv/ssd-one-musique</strong><br />
|
|||
|
Première connexion admin admin</p>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-03-09T00:00:00+01:00"><!-- start custom article footer snippet -->
|
|||
|
|
|||
|
<!-- end custom article footer snippet -->
|
|||
|
<!--
|
|||
|
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
|
|||
|
|
|||
|
 </div>
|
|||
|
-->
|
|||
|
</footer>
|
|||
|
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/03/06/OpenDkim-Spf.html">Opendkim ,identifier ses mails avec le principe DKIM</a></div><div class="next"><span>SUIVANT</span><a href="/2019/03/15/Compile-Allwinner-based-A20-Boards.html">Compile Olimex Allwinner A20 Boards</a></div></div></div>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
$(function() {
|
|||
|
var $this ,$scroll;
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
|
|||
|
$scroll = $(scroll);
|
|||
|
|
|||
|
$articleContent.find('.highlight').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.attr('data-lang', $this.find('code').attr('data-lang'));
|
|||
|
});
|
|||
|
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
|
|||
|
});
|
|||
|
$articleContent.on('click', '.anchor', function() {
|
|||
|
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
})();
|
|||
|
</script>
|
|||
|
|
|||
|
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
|
|||
|
<!-- end custom main bottom snippet -->
|
|||
|
</div>
|
|||
|
</div></div></div></div>
|
|||
|
</div><script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $body = $('body'), $window = $(window);
|
|||
|
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
|
|||
|
var activeCount = 0;
|
|||
|
function modal(options) {
|
|||
|
var $root = this, visible, onChange, hideWhenWindowScroll = false;
|
|||
|
var scrollTop;
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
visible = _options.initialVisible === undefined ? false : show;
|
|||
|
onChange = _options.onChange;
|
|||
|
hideWhenWindowScroll = _options.hideWhenWindowScroll;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
setState(visible);
|
|||
|
}
|
|||
|
function setState(isShow) {
|
|||
|
if (isShow === visible) {
|
|||
|
return;
|
|||
|
}
|
|||
|
visible = isShow;
|
|||
|
if (visible) {
|
|||
|
activeCount++;
|
|||
|
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
|
|||
|
$root.addClass('modal--show');
|
|||
|
$pageMain.scrollTop(scrollTop);
|
|||
|
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
|
|||
|
$window.on('keyup', handleKeyup);
|
|||
|
} else {
|
|||
|
activeCount > 0 && activeCount--;
|
|||
|
$root.removeClass('modal--show');
|
|||
|
$window.scrollTop(scrollTop);
|
|||
|
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
|
|||
|
$window.off('keyup', handleKeyup);
|
|||
|
}
|
|||
|
onChange && onChange(visible);
|
|||
|
}
|
|||
|
function show() {
|
|||
|
setState(true);
|
|||
|
}
|
|||
|
function hide() {
|
|||
|
setState(false);
|
|||
|
}
|
|||
|
function handleKeyup(e) {
|
|||
|
// Char Code: 27 ESC
|
|||
|
if (e.which === 27) {
|
|||
|
hide();
|
|||
|
}
|
|||
|
}
|
|||
|
setOptions(options);
|
|||
|
init();
|
|||
|
return {
|
|||
|
show: show,
|
|||
|
hide: hide,
|
|||
|
$el: $root
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.modal = modal;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
|
|||
|
(function () {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
// search panel
|
|||
|
var search = (window.search || (window.search = {}));
|
|||
|
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
|
|||
|
true : window.useDefaultSearchBox ;
|
|||
|
|
|||
|
var $searchModal = $('.js-page-search-modal');
|
|||
|
var $searchToggle = $('.js-search-toggle');
|
|||
|
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
|
|||
|
var modalVisible = false;
|
|||
|
search.searchModal = searchModal;
|
|||
|
|
|||
|
var $searchBox = null;
|
|||
|
var $searchInput = null;
|
|||
|
var $searchClear = null;
|
|||
|
|
|||
|
function getModalVisible() {
|
|||
|
return modalVisible;
|
|||
|
}
|
|||
|
search.getModalVisible = getModalVisible;
|
|||
|
|
|||
|
function handleModalChange(visible) {
|
|||
|
modalVisible = visible;
|
|||
|
if (visible) {
|
|||
|
search.onShow && search.onShow();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
|
|||
|
} else {
|
|||
|
search.onShow && search.onHide();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
|
|||
|
setTimeout(function() {
|
|||
|
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
|
|||
|
search.clear && search.clear();
|
|||
|
window.pageAsideAffix && window.pageAsideAffix.refresh();
|
|||
|
}, 400);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
$searchToggle.on('click', function() {
|
|||
|
modalVisible ? searchModal.hide() : searchModal.show();
|
|||
|
});
|
|||
|
// Char Code: 83 S, 191 /
|
|||
|
$(window).on('keyup', function(e) {
|
|||
|
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
|
|||
|
modalVisible || searchModal.show();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if (useDefaultSearchBox) {
|
|||
|
$searchBox = $('.js-search-box');
|
|||
|
$searchInput = $searchBox.children('input');
|
|||
|
$searchClear = $searchBox.children('.js-icon-clear');
|
|||
|
search.getSearchInput = function() {
|
|||
|
return $searchInput.get(0);
|
|||
|
};
|
|||
|
search.getVal = function() {
|
|||
|
return $searchInput.val();
|
|||
|
};
|
|||
|
search.setVal = function(val) {
|
|||
|
$searchInput.val(val);
|
|||
|
};
|
|||
|
|
|||
|
$searchInput.on('focus', function() {
|
|||
|
$(this).addClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('blur', function() {
|
|||
|
$(this).removeClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('input', window.throttle(function() {
|
|||
|
var val = $(this).val();
|
|||
|
if (val === '' || typeof val !== 'string') {
|
|||
|
search.clear && search.clear();
|
|||
|
} else {
|
|||
|
$searchBox.addClass('not-empty');
|
|||
|
search.onInputNotEmpty && search.onInputNotEmpty(val);
|
|||
|
}
|
|||
|
}, 400));
|
|||
|
$searchClear.on('click', function() {
|
|||
|
$searchInput.val(''); $searchBox.removeClass('not-empty');
|
|||
|
search.clear && search.clear();
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="search search--dark">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header">Recherche</div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
|
|||
|
Annuler</button>
|
|||
|
</div>
|
|||
|
<div id="results-container" class="search-result js-search-result"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
noResultsText: '<p>Aucun résultat!</p>',
|
|||
|
json: '/search.json',
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a> (Création {create})</li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
|
|||
|
</div></div>
|
|||
|
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function scrollToAnchor(anchor, duration, callback) {
|
|||
|
var $root = this;
|
|||
|
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
|
|||
|
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
|
|||
|
callback && callback();
|
|||
|
});
|
|||
|
}
|
|||
|
$.fn.scrollToAnchor = scrollToAnchor;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function affix(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroll,
|
|||
|
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
|
|||
|
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
|
|||
|
hasInit = false, curState;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroll && (scroll = _options.scroll);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
|
|||
|
$scroll = $(scroll);
|
|||
|
}
|
|||
|
function preCalc() {
|
|||
|
top();
|
|||
|
rootHeight = $root.outerHeight();
|
|||
|
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
|
|||
|
rootLeft = $root.offset().left;
|
|||
|
}
|
|||
|
function calc(needPreCalc) {
|
|||
|
needPreCalc && preCalc();
|
|||
|
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
|
|||
|
rootBottomTop = scrollBottom - rootTop;
|
|||
|
}
|
|||
|
function top() {
|
|||
|
if (curState !== 'top') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'top';
|
|||
|
}
|
|||
|
}
|
|||
|
function fixed() {
|
|||
|
if (curState !== 'fixed') {
|
|||
|
$root.addClass('fixed').css({
|
|||
|
left: rootLeft + 'px',
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'fixed';
|
|||
|
}
|
|||
|
}
|
|||
|
function bottom() {
|
|||
|
if (curState !== 'bottom') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: rootBottomTop + 'px'
|
|||
|
});
|
|||
|
curState = 'bottom';
|
|||
|
}
|
|||
|
}
|
|||
|
function setState() {
|
|||
|
var scrollTop = $scrollTarget.scrollTop();
|
|||
|
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
|
|||
|
fixed();
|
|||
|
} else if (scrollTop < rootTop) {
|
|||
|
top();
|
|||
|
} else {
|
|||
|
bottom();
|
|||
|
}
|
|||
|
}
|
|||
|
function init() {
|
|||
|
if(!hasInit) {
|
|||
|
var interval, timeout;
|
|||
|
calc(true); setState();
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState();
|
|||
|
});
|
|||
|
$window.on('resize', function() {
|
|||
|
disabled || (calc(true), setState());
|
|||
|
});
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions,
|
|||
|
refresh: function() {
|
|||
|
calc(true, { animation: false }); setState();
|
|||
|
}
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.affix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function toc(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
|
|||
|
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
|
|||
|
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.selectors && (selectors = _options.selectors);
|
|||
|
_options.container && (container = _options.container);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroller && (scroller = _options.scroller);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$headings = $(container).find(selectors).filter('[id]');
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
$scroller = $(scroller);
|
|||
|
}
|
|||
|
function calc() {
|
|||
|
headingsPos = [];
|
|||
|
$headings.each(function() {
|
|||
|
headingsPos.push(Math.floor($(this).position().top));
|
|||
|
});
|
|||
|
}
|
|||
|
function setState(element, disabled) {
|
|||
|
var scrollTop = $scrollTarget.scrollTop(), i;
|
|||
|
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
|
|||
|
if (element) {
|
|||
|
$activeCur = element;
|
|||
|
} else {
|
|||
|
for (i = 0; i < headingsPos.length; i++) {
|
|||
|
if (scrollTop >= headingsPos[i]) {
|
|||
|
$activeCur = $tocLi.eq(i);
|
|||
|
} else {
|
|||
|
$activeCur || ($activeCur = $tocLi.eq(i));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$activeLast && $activeLast.removeClass('active');
|
|||
|
($activeLast = $activeCur).addClass('active');
|
|||
|
}
|
|||
|
function render() {
|
|||
|
if(!hasRendered) {
|
|||
|
$root.append($tocUl);
|
|||
|
$headings.each(function() {
|
|||
|
var $this = $(this);
|
|||
|
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
|
|||
|
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
|
|||
|
});
|
|||
|
$tocLi = $tocUl.children('li');
|
|||
|
$tocUl.on('click', 'a', function(e) {
|
|||
|
e.preventDefault();
|
|||
|
var $this = $(this);
|
|||
|
scrolling = true;
|
|||
|
setState($this.parent());
|
|||
|
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
|
|||
|
scrolling = false;
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
hasRendered = true;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
var interval, timeout;
|
|||
|
if(!hasInit) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState(null, scrolling);
|
|||
|
});
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
if (!disabled) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
}
|
|||
|
}, 100));
|
|||
|
}
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.toc = toc;
|
|||
|
});
|
|||
|
})();
|
|||
|
/*(function () {
|
|||
|
|
|||
|
})();*/
|
|||
|
</script><script>
|
|||
|
/* toc must before affix, since affix need to konw toc' height. */(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window);
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
|
|||
|
var toc;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
|
|||
|
|
|||
|
function disabled() {
|
|||
|
return $col2.css('display') === 'none' || !hasToc;
|
|||
|
}
|
|||
|
|
|||
|
tocDisabled = disabled();
|
|||
|
|
|||
|
toc = $tocRoot.toc({
|
|||
|
selectors: TOC_SELECTOR,
|
|||
|
container: $articleContent,
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
tocDisabled = disabled();
|
|||
|
toc && toc.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window), $pageFooter = $('.js-page-footer');
|
|||
|
var $pageAside = $('.js-page-aside');
|
|||
|
var affix;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
|
|||
|
affix = $pageAside.affix({
|
|||
|
offsetBottom: $pageFooter.outerHeight(),
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroll: hasSidebar ? $('.js-page-main').children() : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
affix && affix.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
window.pageAsideAffix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><!---->
|
|||
|
|
|||
|
</div>
|
|||
|
<script>(function () {
|
|||
|
var $root = document.getElementsByClassName('root')[0];
|
|||
|
if (window.hasEvent('touchstart')) {
|
|||
|
$root.dataset.isTouch = true;
|
|||
|
document.addEventListener('touchstart', function(){}, false);
|
|||
|
}
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
|