From ba76cefc39e0b9b50dd8416e76f4d3e6f6ce8aff Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 21:49:14 +0100 Subject: [PATCH 01/28] add github actions --- .github/styles/Google/AMPM.yml | 9 + .github/styles/Google/Acronyms.yml | 64 +++++++ .github/styles/Google/Colons.yml | 7 + .github/styles/Google/Contractions.yml | 28 +++ .github/styles/Google/DateFormat.yml | 9 + .github/styles/Google/Ellipses.yml | 7 + .github/styles/Google/EmDash.yml | 8 + .github/styles/Google/EnDash.yml | 7 + .github/styles/Google/Exclamation.yml | 7 + .github/styles/Google/FirstPerson.yml | 11 ++ .github/styles/Google/Gender.yml | 9 + .github/styles/Google/GenderBias.yml | 45 +++++ .github/styles/Google/HeadingPunctuation.yml | 8 + .github/styles/Google/Headings.yml | 26 +++ .github/styles/Google/Hyphens.yml | 8 + .github/styles/Google/Latin.yml | 9 + .github/styles/Google/LyHyphens.yml | 8 + .github/styles/Google/OptionalPlurals.yml | 7 + .github/styles/Google/Ordinal.yml | 7 + .github/styles/Google/OxfordComma.yml | 7 + .github/styles/Google/Parens.yml | 7 + .github/styles/Google/Passive.yml | 184 +++++++++++++++++++ .github/styles/Google/Periods.yml | 7 + .github/styles/Google/Quotes.yml | 7 + .github/styles/Google/Ranges.yml | 7 + .github/styles/Google/Semicolons.yml | 8 + .github/styles/Google/Slang.yml | 11 ++ .github/styles/Google/Spacing.yml | 8 + .github/styles/Google/Spelling.yml | 8 + .github/styles/Google/Units.yml | 7 + .github/styles/Google/Will.yml | 7 + .github/styles/Google/WordList.yml | 79 ++++++++ .github/styles/Google/meta.json | 16 ++ .github/styles/Google/vocab.txt | 0 .github/styles/VyOS/Terminology.yml | 9 + .github/vyos-linter.py | 162 ++++++++++++++++ .github/workflows/main.yml | 32 ++++ .gitmodules | 4 + vale.ini | 16 ++ 39 files changed, 870 insertions(+) create mode 100644 .github/styles/Google/AMPM.yml create mode 100644 .github/styles/Google/Acronyms.yml create mode 100644 .github/styles/Google/Colons.yml create mode 100644 .github/styles/Google/Contractions.yml create mode 100644 .github/styles/Google/DateFormat.yml create mode 100644 .github/styles/Google/Ellipses.yml create mode 100644 .github/styles/Google/EmDash.yml create mode 100644 .github/styles/Google/EnDash.yml create mode 100644 .github/styles/Google/Exclamation.yml create mode 100644 .github/styles/Google/FirstPerson.yml create mode 100644 .github/styles/Google/Gender.yml create mode 100644 .github/styles/Google/GenderBias.yml create mode 100644 .github/styles/Google/HeadingPunctuation.yml create mode 100644 .github/styles/Google/Headings.yml create mode 100644 .github/styles/Google/Hyphens.yml create mode 100644 .github/styles/Google/Latin.yml create mode 100644 .github/styles/Google/LyHyphens.yml create mode 100644 .github/styles/Google/OptionalPlurals.yml create mode 100644 .github/styles/Google/Ordinal.yml create mode 100644 .github/styles/Google/OxfordComma.yml create mode 100644 .github/styles/Google/Parens.yml create mode 100644 .github/styles/Google/Passive.yml create mode 100644 .github/styles/Google/Periods.yml create mode 100644 .github/styles/Google/Quotes.yml create mode 100644 .github/styles/Google/Ranges.yml create mode 100644 .github/styles/Google/Semicolons.yml create mode 100644 .github/styles/Google/Slang.yml create mode 100644 .github/styles/Google/Spacing.yml create mode 100644 .github/styles/Google/Spelling.yml create mode 100644 .github/styles/Google/Units.yml create mode 100644 .github/styles/Google/Will.yml create mode 100644 .github/styles/Google/WordList.yml create mode 100644 .github/styles/Google/meta.json create mode 100644 .github/styles/Google/vocab.txt create mode 100644 .github/styles/VyOS/Terminology.yml create mode 100644 .github/vyos-linter.py create mode 100644 .github/workflows/main.yml create mode 100644 .gitmodules create mode 100644 vale.ini diff --git a/.github/styles/Google/AMPM.yml b/.github/styles/Google/AMPM.yml new file mode 100644 index 00000000..fbdc6e4f --- /dev/null +++ b/.github/styles/Google/AMPM.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Use 'AM' or 'PM' (preceded by a space)." +link: 'https://developers.google.com/style/word-list' +level: error +nonword: true +tokens: + - '\d{1,2}[AP]M' + - '\d{1,2} ?[ap]m' + - '\d{1,2} ?[aApP]\.[mM]\.' diff --git a/.github/styles/Google/Acronyms.yml b/.github/styles/Google/Acronyms.yml new file mode 100644 index 00000000..f41af018 --- /dev/null +++ b/.github/styles/Google/Acronyms.yml @@ -0,0 +1,64 @@ +extends: conditional +message: "Spell out '%s', if it's unfamiliar to the audience." +link: 'https://developers.google.com/style/abbreviations' +level: suggestion +ignorecase: false +# Ensures that the existence of 'first' implies the existence of 'second'. +first: '\b([A-Z]{3,5})\b' +second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' +# ... with the exception of these: +exceptions: + - API + - ASP + - CLI + - CPU + - CSS + - CSV + - DEBUG + - DOM + - DPI + - FAQ + - GCC + - GDB + - GET + - GPU + - GTK + - GUI + - HTML + - HTTP + - HTTPS + - IDE + - JAR + - JSON + - JSX + - LESS + - LLDB + - NET + - NOTE + - NVDA + - OSS + - PATH + - PDF + - PHP + - POST + - RAM + - REPL + - RSA + - SCM + - SCSS + - SDK + - SQL + - SSH + - SSL + - SVG + - TBD + - TCP + - TODO + - URI + - URL + - USB + - UTF + - XML + - XSS + - YAML + - ZIP diff --git a/.github/styles/Google/Colons.yml b/.github/styles/Google/Colons.yml new file mode 100644 index 00000000..9a4b4b4a --- /dev/null +++ b/.github/styles/Google/Colons.yml @@ -0,0 +1,7 @@ +extends: existence +message: "'%s' should be in lowercase." +link: 'https://developers.google.com/style/colons' +nonword: true +level: warning +tokens: + - ':\s[A-Z]' diff --git a/.github/styles/Google/Contractions.yml b/.github/styles/Google/Contractions.yml new file mode 100644 index 00000000..905a39f4 --- /dev/null +++ b/.github/styles/Google/Contractions.yml @@ -0,0 +1,28 @@ +extends: substitution +message: "Feel free to use '%s' instead of '%s'." +link: 'https://developers.google.com/style/contractions' +level: suggestion +ignorecase: true +swap: + are not: aren't + cannot: can't + could not: couldn't + did not: didn't + do not: don't + does not: doesn't + has not: hasn't + have not: haven't + how is: how's + is not: isn't + it is: it's + should not: shouldn't + that is: that's + they are: they're + was not: wasn't + we are: we're + we have: we've + were not: weren't + what is: what's + when is: when's + where is: where's + will not: won't diff --git a/.github/styles/Google/DateFormat.yml b/.github/styles/Google/DateFormat.yml new file mode 100644 index 00000000..e9d227fa --- /dev/null +++ b/.github/styles/Google/DateFormat.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Use 'July 31, 2016' format, not '%s'." +link: 'https://developers.google.com/style/dates-times' +ignorecase: true +level: error +nonword: true +tokens: + - '\d{1,2}(?:\.|/)\d{1,2}(?:\.|/)\d{4}' + - '\d{1,2} (?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)|May|Jun(?:e)|Jul(?:y)|Aug(?:ust)|Sep(?:tember)?|Oct(?:ober)|Nov(?:ember)?|Dec(?:ember)?) \d{4}' diff --git a/.github/styles/Google/Ellipses.yml b/.github/styles/Google/Ellipses.yml new file mode 100644 index 00000000..436e6177 --- /dev/null +++ b/.github/styles/Google/Ellipses.yml @@ -0,0 +1,7 @@ +extends: existence +message: "In general, don't use an ellipsis." +link: 'https://developers.google.com/style/ellipses' +nonword: true +level: warning +tokens: + - '\.\.\.' diff --git a/.github/styles/Google/EmDash.yml b/.github/styles/Google/EmDash.yml new file mode 100644 index 00000000..c6018db1 --- /dev/null +++ b/.github/styles/Google/EmDash.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Don't put a space before or after an em dash." +link: 'https://developers.google.com/style/dashes' +nonword: true +level: error +tokens: + - '\s—' + - '—\s' diff --git a/.github/styles/Google/EnDash.yml b/.github/styles/Google/EnDash.yml new file mode 100644 index 00000000..194876aa --- /dev/null +++ b/.github/styles/Google/EnDash.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Use an em dash ('—') instead of '–'." +link: 'https://developers.google.com/style/dashes' +nonword: true +level: error +tokens: + - '–' diff --git a/.github/styles/Google/Exclamation.yml b/.github/styles/Google/Exclamation.yml new file mode 100644 index 00000000..c4db380b --- /dev/null +++ b/.github/styles/Google/Exclamation.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't use exclamation points in text." +link: 'https://developers.google.com/style/exclamation-points' +nonword: true +level: error +tokens: + - '!' diff --git a/.github/styles/Google/FirstPerson.yml b/.github/styles/Google/FirstPerson.yml new file mode 100644 index 00000000..d2290611 --- /dev/null +++ b/.github/styles/Google/FirstPerson.yml @@ -0,0 +1,11 @@ +extends: existence +message: "Avoid first-person pronouns such as '%s'." +link: 'https://developers.google.com/style/pronouns#personal-pronouns' +ignorecase: true +level: warning +nonword: true +tokens: + - (?:^|\s)I\s + - \bme\b + - \bus\b + - \bours\b diff --git a/.github/styles/Google/Gender.yml b/.github/styles/Google/Gender.yml new file mode 100644 index 00000000..c8486181 --- /dev/null +++ b/.github/styles/Google/Gender.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Don't use '%s' as a gender-neutral pronoun." +link: 'https://developers.google.com/style/pronouns#gender-neutral-pronouns' +level: error +ignorecase: true +tokens: + - he/she + - s/he + - \(s\)he diff --git a/.github/styles/Google/GenderBias.yml b/.github/styles/Google/GenderBias.yml new file mode 100644 index 00000000..261cfb66 --- /dev/null +++ b/.github/styles/Google/GenderBias.yml @@ -0,0 +1,45 @@ +extends: substitution +message: "Consider using '%s' instead of '%s'." +link: 'https://developers.google.com/style/inclusive-documentation' +ignorecase: true +level: error +swap: + (?:alumna|alumnus): graduate + (?:alumnae|alumni): graduates + air(?:m[ae]n|wom[ae]n): pilot(s) + anchor(?:m[ae]n|wom[ae]n): anchor(s) + authoress: author + camera(?:m[ae]n|wom[ae]n): camera operator(s) + chair(?:m[ae]n|wom[ae]n): chair(s) + congress(?:m[ae]n|wom[ae]n): member(s) of congress + door(?:m[ae]|wom[ae]n): concierge(s) + draft(?:m[ae]n|wom[ae]n): drafter(s) + fire(?:m[ae]n|wom[ae]n): firefighter(s) + fisher(?:m[ae]n|wom[ae]n): fisher(s) + fresh(?:m[ae]n|wom[ae]n): first-year student(s) + garbage(?:m[ae]n|wom[ae]n): waste collector(s) + lady lawyer: lawyer + ladylike: courteous + landlord: building manager + mail(?:m[ae]n|wom[ae]n): mail carriers + man and wife: husband and wife + man enough: strong enough + mankind: human kind + manmade: manufactured + manpower: personnel + men and girls: men and women + middle(?:m[ae]n|wom[ae]n): intermediary + news(?:m[ae]n|wom[ae]n): journalist(s) + ombuds(?:man|woman): ombuds + oneupmanship: upstaging + poetess: poet + police(?:m[ae]n|wom[ae]n): police officer(s) + repair(?:m[ae]n|wom[ae]n): technician(s) + sales(?:m[ae]n|wom[ae]n): salesperson or sales people + service(?:m[ae]n|wom[ae]n): soldier(s) + steward(?:ess)?: flight attendant + tribes(?:m[ae]n|wom[ae]n): tribe member(s) + waitress: waiter + woman doctor: doctor + woman scientist[s]?: scientist(s) + work(?:m[ae]n|wom[ae]n): worker(s) diff --git a/.github/styles/Google/HeadingPunctuation.yml b/.github/styles/Google/HeadingPunctuation.yml new file mode 100644 index 00000000..5c39abbf --- /dev/null +++ b/.github/styles/Google/HeadingPunctuation.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Don't put a period at the end of a heading." +link: 'https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings' +nonword: true +level: warning +scope: heading +tokens: + - '[a-z0-9][.](?:\s|$)' diff --git a/.github/styles/Google/Headings.yml b/.github/styles/Google/Headings.yml new file mode 100644 index 00000000..5afb968d --- /dev/null +++ b/.github/styles/Google/Headings.yml @@ -0,0 +1,26 @@ +extends: capitalization +message: "'%s' should use sentence-style capitalization." +link: 'https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings' +level: warning +scope: heading +match: $sentence +exceptions: + - Azure + - CLI + - Code + - Cosmos + - Docker + - Emmet + - I + - Kubernetes + - Linux + - macOS + - Marketplace + - MongoDB + - REPL + - Studio + - TypeScript + - URLs + - Visual + - VS + - Windows diff --git a/.github/styles/Google/Hyphens.yml b/.github/styles/Google/Hyphens.yml new file mode 100644 index 00000000..f9779637 --- /dev/null +++ b/.github/styles/Google/Hyphens.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Don't place a space on either side of a hyphen (unless it's suspended)." +link: 'https://developers.google.com/style/hyphens' +level: warning +nonword: true +tokens: + - '\s-' + - '-\s' diff --git a/.github/styles/Google/Latin.yml b/.github/styles/Google/Latin.yml new file mode 100644 index 00000000..f032b349 --- /dev/null +++ b/.github/styles/Google/Latin.yml @@ -0,0 +1,9 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +link: 'https://developers.google.com/style/abbreviations' +ignorecase: true +level: error +nonword: true +swap: + '\b(?:eg|e\.g\.)[\s,]': for example + '\b(?:ie|i\.e\.)[\s,]': that is diff --git a/.github/styles/Google/LyHyphens.yml b/.github/styles/Google/LyHyphens.yml new file mode 100644 index 00000000..d5b6a942 --- /dev/null +++ b/.github/styles/Google/LyHyphens.yml @@ -0,0 +1,8 @@ +extends: existence +message: "'%s' doesn't need a hyphen." +link: 'https://developers.google.com/style/hyphens' +level: error +ignorecase: false +nonword: true +tokens: + - '\s[^\s-]+ly-' diff --git a/.github/styles/Google/OptionalPlurals.yml b/.github/styles/Google/OptionalPlurals.yml new file mode 100644 index 00000000..7058932f --- /dev/null +++ b/.github/styles/Google/OptionalPlurals.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't use plurals in parentheses such as in '%s'." +link: 'https://developers.google.com/style/plurals-parentheses' +level: error +nonword: true +tokens: + - '\b\w+\(s\)' diff --git a/.github/styles/Google/Ordinal.yml b/.github/styles/Google/Ordinal.yml new file mode 100644 index 00000000..8c429e0f --- /dev/null +++ b/.github/styles/Google/Ordinal.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Spell out all ordinal numbers ('%s') in text." +link: 'https://developers.google.com/style/numbers' +level: error +nonword: true +tokens: + - \d+(?:st|th|rd) diff --git a/.github/styles/Google/OxfordComma.yml b/.github/styles/Google/OxfordComma.yml new file mode 100644 index 00000000..98b07113 --- /dev/null +++ b/.github/styles/Google/OxfordComma.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Use the Oxford comma in '%s'." +link: 'https://developers.google.com/style/commas' +scope: sentence +level: warning +tokens: + - '(?:[^,]+,){1,}\s\w+\sand' diff --git a/.github/styles/Google/Parens.yml b/.github/styles/Google/Parens.yml new file mode 100644 index 00000000..3b8711d0 --- /dev/null +++ b/.github/styles/Google/Parens.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Use parentheses judiciously." +link: 'https://developers.google.com/style/parentheses' +nonword: true +level: suggestion +tokens: + - '\(.+\)' diff --git a/.github/styles/Google/Passive.yml b/.github/styles/Google/Passive.yml new file mode 100644 index 00000000..3265890e --- /dev/null +++ b/.github/styles/Google/Passive.yml @@ -0,0 +1,184 @@ +extends: existence +link: 'https://developers.google.com/style/voice' +message: "In general, use active voice instead of passive voice ('%s')." +ignorecase: true +level: suggestion +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung diff --git a/.github/styles/Google/Periods.yml b/.github/styles/Google/Periods.yml new file mode 100644 index 00000000..d24a6a6c --- /dev/null +++ b/.github/styles/Google/Periods.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't use periods with acronyms or initialisms such as '%s'." +link: 'https://developers.google.com/style/abbreviations' +level: error +nonword: true +tokens: + - '\b(?:[A-Z]\.){3,}' diff --git a/.github/styles/Google/Quotes.yml b/.github/styles/Google/Quotes.yml new file mode 100644 index 00000000..3cb6f1ab --- /dev/null +++ b/.github/styles/Google/Quotes.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Commas and periods go inside quotation marks." +link: 'https://developers.google.com/style/quotation-marks' +level: error +nonword: true +tokens: + - '"[^"]+"[.,?]' diff --git a/.github/styles/Google/Ranges.yml b/.github/styles/Google/Ranges.yml new file mode 100644 index 00000000..3ec045e7 --- /dev/null +++ b/.github/styles/Google/Ranges.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't add words such as 'from' or 'between' to describe a range of numbers." +link: 'https://developers.google.com/style/hyphens' +nonword: true +level: warning +tokens: + - '(?:from|between)\s\d+\s?-\s?\d+' diff --git a/.github/styles/Google/Semicolons.yml b/.github/styles/Google/Semicolons.yml new file mode 100644 index 00000000..bb8b85b4 --- /dev/null +++ b/.github/styles/Google/Semicolons.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Use semicolons judiciously." +link: 'https://developers.google.com/style/semicolons' +nonword: true +scope: sentence +level: suggestion +tokens: + - ';' diff --git a/.github/styles/Google/Slang.yml b/.github/styles/Google/Slang.yml new file mode 100644 index 00000000..63f4c248 --- /dev/null +++ b/.github/styles/Google/Slang.yml @@ -0,0 +1,11 @@ +extends: existence +message: "Don't use internet slang abbreviations such as '%s'." +link: 'https://developers.google.com/style/abbreviations' +ignorecase: true +level: error +tokens: + - 'tl;dr' + - ymmv + - rtfm + - imo + - fwiw diff --git a/.github/styles/Google/Spacing.yml b/.github/styles/Google/Spacing.yml new file mode 100644 index 00000000..5f209a9f --- /dev/null +++ b/.github/styles/Google/Spacing.yml @@ -0,0 +1,8 @@ +extends: existence +message: "'%s' should have one space." +link: 'https://developers.google.com/style/sentence-spacing' +level: error +nonword: true +tokens: + - '[.?!] {2,}[A-Z]' + - '[.?!][A-Z]' diff --git a/.github/styles/Google/Spelling.yml b/.github/styles/Google/Spelling.yml new file mode 100644 index 00000000..57acb884 --- /dev/null +++ b/.github/styles/Google/Spelling.yml @@ -0,0 +1,8 @@ +extends: existence +message: "In general, use American spelling instead of '%s'." +link: 'https://developers.google.com/style/spelling' +ignorecase: true +level: warning +tokens: + - '(?:\w+)nised?' + - '(?:\w+)logue' diff --git a/.github/styles/Google/Units.yml b/.github/styles/Google/Units.yml new file mode 100644 index 00000000..220de3e9 --- /dev/null +++ b/.github/styles/Google/Units.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Put a nonbreaking space between the number and the unit in '%s'." +link: 'https://developers.google.com/style/units-of-measure' +nonword: true +level: error +tokens: + - \d+(?:GB|TB|MB) diff --git a/.github/styles/Google/Will.yml b/.github/styles/Google/Will.yml new file mode 100644 index 00000000..128a9183 --- /dev/null +++ b/.github/styles/Google/Will.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Avoid using '%s'." +link: 'https://developers.google.com/style/tense' +ignorecase: true +level: warning +tokens: + - will diff --git a/.github/styles/Google/WordList.yml b/.github/styles/Google/WordList.yml new file mode 100644 index 00000000..d5d6bea5 --- /dev/null +++ b/.github/styles/Google/WordList.yml @@ -0,0 +1,79 @@ +extends: substitution +message: "Use %s instead of '%s'." +link: 'https://developers.google.com/style/word-list' +level: warning +ignorecase: false +swap: + '(?:API Console|dev|developer) key': "'API key'" + '(?:cell ?phone|smart ?phone)': "'phone' or 'mobile phone'" + '(?:dev|developer|APIs) console': "'API console'" + '(?:e-mail|Email|E-mail)': "'email'" + '(?:file ?path|path ?name)': "'path'" + '(?:kill|terminate)': "'stop', 'exit', 'cancel', or 'end'" + '(?:OAuth ?2|Oauth)': "'OAuth 2.0'" + '(?:ok|Okay)': "'OK' or 'okay'" + '(?:WiFi|wifi)': "'Wi-Fi'" + '[\.]+apk': "'APK'" + '3\-D': "'3D'" + 'Google (?:I\-O|IO)': "'Google I/O'" + 'tap (?:&|and) hold': "'touch & hold'" + 'un(?:check|select)': "'clear'" + abort: "'stop', 'exit', 'cancel' or 'end'" + above: "'preceding'" + account name: "'username'" + action bar: "'app bar'" + admin: "'administrator'" + Ajax: "'AJAX'" + Android device: "'Android-powered device'" + android: "'Android'" + API explorer: "'APIs Explorer'" + application: "'app'" + approx\.: "'approximately'" + authN: "'authentication'" + authZ: "'authorization'" + autoupdate: "'automatically update'" + cellular data: "'mobile data'" + cellular network: "'mobile network'" + chapter: "'documents', 'pages', 'sections'" + check box: "'checkbox'" + check: "'select'" + CLI: "'command-line tool'" + click on: "'click' or 'click in'" + Cloud: "'Google Cloud Platform' or 'GCP'" + Container Engine: "'Kubernetes Engine'" + content type: "'media type'" + curated roles: "'predefined roles'" + data are: "'data is'" + Developers Console: "'Google API Console' or 'API Console'" + disabled?: "'turn off' or 'off'" + ephemeral IP address: "'ephemeral external IP address'" + fewer data: "'less data'" + file name: "'filename'" + firewalls: "'firewall rules'" + functionality: "'capability' or 'feature'" + Google account: "'Google Account'" + Google accounts: "'Google Accounts'" + Googling: "'search with Google'" + grayed-out: "'unavailable'" + HTTPs: "'HTTPS'" + in order to: "'to'" + ingest: "'import' or 'load'" + k8s: "'Kubernetes'" + long press: "'touch & hold'" + network IP address: "'internal IP address'" + omnibox: "'address bar'" + open-source: "'open source'" + overview screen: "'recents screen'" + regex: "'regular expression'" + SHA1: "'SHA-1' or 'HAS-SHA1'" + sign into: "'sign in to'" + sign-?on: "'single sign-on'" + static IP address: "'static external IP address'" + stylesheet: "'style sheet'" + synch: "'sync'" + tablename: "'table name'" + tablet: "'device'" + touch: "'tap'" + url: "'URL'" + vs\.: "'versus'" + World Wide Web: "'web'" diff --git a/.github/styles/Google/meta.json b/.github/styles/Google/meta.json new file mode 100644 index 00000000..3ae5fb21 --- /dev/null +++ b/.github/styles/Google/meta.json @@ -0,0 +1,16 @@ +{ + "author": "Joseph Kato", + "description": "A Vale-compatible implementation of the Microsoft Writing Style Guide.", + "email": "support@errata.ai", + "lang": "en", + "url": "https://github.com/errata-ai/Google/releases/latest/download/Google.zip", + "feed": "https://github.com/errata-ai/Google/releases.atom", + "issues": "https://github.com/errata-ai/Google/issues/new", + "license": "MIT", + "name": "Google", + "sources": [ + "https://developers.google.com/style/" + ], + "vale_version": ">=1.0.0", + "coverage": 0.0 +} diff --git a/.github/styles/Google/vocab.txt b/.github/styles/Google/vocab.txt new file mode 100644 index 00000000..e69de29b diff --git a/.github/styles/VyOS/Terminology.yml b/.github/styles/VyOS/Terminology.yml new file mode 100644 index 00000000..cd0c5089 --- /dev/null +++ b/.github/styles/VyOS/Terminology.yml @@ -0,0 +1,9 @@ +extends: substitution +message: Prefer '%s' over '%s' +ignorecase: false +level: error +swap: + vyos: VyOS + Vyos: VyOS + VYOS: VyOS + Gre: GRE \ No newline at end of file diff --git a/.github/vyos-linter.py b/.github/vyos-linter.py new file mode 100644 index 00000000..05bb6bbb --- /dev/null +++ b/.github/vyos-linter.py @@ -0,0 +1,162 @@ +import os +import re +import ipaddress +import sys +import ast + +IPV4SEG = r'(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])' +IPV4ADDR = r'(?:(?:' + IPV4SEG + r'\.){3,3}' + IPV4SEG + r')' +IPV6SEG = r'(?:(?:[0-9a-fA-F]){1,4})' +IPV6GROUPS = ( + r'(?:' + IPV6SEG + r':){7,7}' + IPV6SEG, # 1:2:3:4:5:6:7:8 + r'(?:\s' + IPV6SEG + r':){1,7}:', # 1:: 1:2:3:4:5:6:7:: + r'(?:' + IPV6SEG + r':){1,6}:' + IPV6SEG, # 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8 + r'(?:' + IPV6SEG + r':){1,5}(?::' + IPV6SEG + r'){1,2}', # 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8 + r'(?:' + IPV6SEG + r':){1,4}(?::' + IPV6SEG + r'){1,3}', # 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8 + r'(?:' + IPV6SEG + r':){1,3}(?::' + IPV6SEG + r'){1,4}', # 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8 + r'(?:' + IPV6SEG + r':){1,2}(?::' + IPV6SEG + r'){1,5}', # 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8 + IPV6SEG + r':(?:(?::' + IPV6SEG + r'){1,6})', # 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8 + r':(?:(?::' + IPV6SEG + r'){1,7}|:)', # ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 :: + r'fe80:(?::' + IPV6SEG + r'){0,4}%[0-9a-zA-Z]{1,}', # fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index) + r'::(?:ffff(?::0{1,4}){0,1}:){0,1}[^\s:]' + IPV4ADDR, # ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses) + r'(?:' + IPV6SEG + r':){1,4}:[^\s:]' + IPV4ADDR, # 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address) +) +IPV6ADDR = '|'.join(['(?:{})'.format(g) for g in IPV6GROUPS[::-1]]) # Reverse rows for greedy match + +MAC = r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})' + +NUMBER = r"([\s']\d+[\s'])" + + +def lint_mac(cnt, line): + mac = re.search(MAC, line, re.I) + if mac is not None: + mac = mac.group() + u_mac = re.search(r'((00)[:-](53)([:-][0-9A-F]{2}){4})', mac, re.I) + m_mac = re.search(r'((90)[:-](10)([:-][0-9A-F]{2}){4})', mac, re.I) + if u_mac is None and m_mac is None: + return (f"Use MAC reserved for Documentation (RFC7042): {mac}", cnt, 'error') + + +def lint_ipv4(cnt, line): + ip = re.search(IPV4ADDR, line, re.I) + if ip is not None: + ip = ipaddress.ip_address(ip.group().strip(' ')) + # https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.is_private + if ip.is_private is False and ip.is_multicast is False: + return (f"Use IPv4 reserved for Documentation (RFC 5737) or private Space: {ip}", cnt, 'error') + + +def lint_ipv6(cnt, line): + ip = re.search(IPV6ADDR, line, re.I) + if ip is not None: + ip = ipaddress.ip_address(ip.group().strip(' ')) + # https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.is_private + if ip.is_private is False and ip.is_multicast is False: + return (f"Use IPv6 reserved for Documentation (RFC 3849) or private Space: {ip}", cnt, 'error') + + +def lint_AS(cnt, line): + number = re.search(NUMBER, line, re.I) + if number: + pass + # find a way to detect AS numbers + + +def lint_linelen(cnt, line): + if len(line) > 80: + return (f"Line too long: len={len(line)}", cnt, 'warning') + + +def handle_file(path, file): + errors = [] + path = '/'.join(path) + filepath = f"{path}/{file}" + try: + with open(filepath) as fp: + line = fp.readline() + cnt = 1 + while line: + err_mac = lint_mac(cnt, line.strip()) + err_ip4 = lint_ipv4(cnt, line.strip()) + err_ip6 = lint_ipv6(cnt, line.strip()) + err_len = lint_linelen(cnt, line.strip()) + if err_mac: + errors.append(err_mac) + if err_ip4: + errors.append(err_ip4) + if err_ip6: + errors.append(err_ip6) + if err_len: + errors.append(err_len) + line = fp.readline() + cnt += 1 + finally: + fp.close() + + if len(errors) > 0: + print(f"File: {filepath}") + for error in errors: + print(error) + print('') + return False + +def handle_file_action(filepath): + errors = [] + try: + with open(filepath) as fp: + line = fp.readline() + cnt = 1 + while line: + err_mac = lint_mac(cnt, line.strip()) + err_ip4 = lint_ipv4(cnt, line.strip()) + err_ip6 = lint_ipv6(cnt, line.strip()) + err_len = lint_linelen(cnt, line.strip()) + if err_mac: + errors.append(err_mac) + if err_ip4: + errors.append(err_ip4) + if err_ip6: + errors.append(err_ip6) + if err_len: + errors.append(err_len) + line = fp.readline() + cnt += 1 + finally: + fp.close() + + if len(errors) > 0: + ''' + "::{$type} file={$filename},line={$line},col=$column::{$log}" + ''' + print(f"File: {filepath}") + for error in errors: + print(f"::{error[2]} file={filepath},line={error[1]}::{error[0]}") + print('') + return False + + +def main(): + bool_error = True + print('start') + try: + files = ast.literal_eval(sys.argv[1]) + for file in files: + print(file) + if file[-4:] == ".rst": + if handle_file_action(file) is False: + bool_error = False + except Exception as e: + print(e) + for root, dirs, files in os.walk("../docs"): + path = root.split(os.sep) + for file in files: + if file[-4:] == ".rst": + if handle_file(path, file) is False: + bool_error = False + return bool_error + + +if __name__ == "__main__": + if main() == False: + exit(1) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..b6797ce0 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,32 @@ +name: Linting +on: + pull_request: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: File Changes + id: file_changes + uses: trilom/file-changes-action@v1.2.3 + + - name: Vale + uses: errata-ai/vale-action@v1.3.0 + with: + files: '${{ steps.file_changes.outputs.files_modified }}' + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: run python based linter + run: python .github/vyos-linter.py '${{ steps.file_changes.outputs.files_modified }}' + + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..d3d92138 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "docs/_include/vyos-1x"] + path = docs/_include/vyos-1x + url = https://github.com/vyos/vyos-1x + branch = current diff --git a/vale.ini b/vale.ini new file mode 100644 index 00000000..b7dde1d8 --- /dev/null +++ b/vale.ini @@ -0,0 +1,16 @@ +StylesPath = .github/styles +MinAlertLevel = suggestion + +SkippedScopes = script, style, pre, figure, img, a, code + + +[*.rst] +BasedOnStyles = VyOS, Google + +Google.DateFormat = YES +vale.GenderBias = NO +vale.Hedging = NO +vale.Redundancy = NO +vale.Repetition = YES +vale.Uncomparables = NO +proselint.GenderBias = NO \ No newline at end of file From 3e5366f95ce02f8c9e31a9a2e1001621176100cc Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 21:50:17 +0100 Subject: [PATCH 02/28] add github submodule to readthedocs.yml --- .readthedocs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.readthedocs.yml b/.readthedocs.yml index db36f18f..7a4e84da 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -22,3 +22,7 @@ python: version: 3.7 install: - requirements: requirements.txt + +submodules: + include: + - vyos-1x \ No newline at end of file From 27022c6a9c7c4ec57eb79cc17475b4d7d03a22cc Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 21:51:54 +0100 Subject: [PATCH 03/28] prepare coverage --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fc8e190e..2b1f7796 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ Sphinx>=1.4.3 sphinx-rtd-theme setuptools docutils -sphinx-notfound-page +lxml +sphinx-notfound-page \ No newline at end of file From ab14c6a43a4fa56e35f6fd8b48bc267611b02f01 Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 21:52:17 +0100 Subject: [PATCH 04/28] move vale stuff to .github --- .vale | 16 --- ci/vale/Google/AMPM.yml | 9 -- ci/vale/Google/Acronyms.yml | 64 --------- ci/vale/Google/Colons.yml | 7 - ci/vale/Google/Contractions.yml | 28 ---- ci/vale/Google/DateFormat.yml | 9 -- ci/vale/Google/Ellipses.yml | 7 - ci/vale/Google/EmDash.yml | 8 -- ci/vale/Google/EnDash.yml | 7 - ci/vale/Google/Exclamation.yml | 7 - ci/vale/Google/FirstPerson.yml | 11 -- ci/vale/Google/Gender.yml | 9 -- ci/vale/Google/GenderBias.yml | 45 ------- ci/vale/Google/HeadingPunctuation.yml | 8 -- ci/vale/Google/Headings.yml | 26 ---- ci/vale/Google/Hyphens.yml | 8 -- ci/vale/Google/Latin.yml | 9 -- ci/vale/Google/LyHyphens.yml | 8 -- ci/vale/Google/OptionalPlurals.yml | 7 - ci/vale/Google/Ordinal.yml | 7 - ci/vale/Google/OxfordComma.yml | 7 - ci/vale/Google/Parens.yml | 7 - ci/vale/Google/Passive.yml | 184 -------------------------- ci/vale/Google/Periods.yml | 7 - ci/vale/Google/Quotes.yml | 7 - ci/vale/Google/Ranges.yml | 7 - ci/vale/Google/Semicolons.yml | 8 -- ci/vale/Google/Slang.yml | 11 -- ci/vale/Google/Spacing.yml | 8 -- ci/vale/Google/Spelling.yml | 8 -- ci/vale/Google/Units.yml | 7 - ci/vale/Google/Will.yml | 7 - ci/vale/Google/WordList.yml | 79 ----------- ci/vale/Google/meta.json | 16 --- ci/vale/Google/vocab.txt | 0 ci/vale/VyOS/Terminology.yml | 9 -- ci/vyos-linter.py | 117 ---------------- 37 files changed, 789 deletions(-) delete mode 100644 .vale delete mode 100644 ci/vale/Google/AMPM.yml delete mode 100644 ci/vale/Google/Acronyms.yml delete mode 100644 ci/vale/Google/Colons.yml delete mode 100644 ci/vale/Google/Contractions.yml delete mode 100644 ci/vale/Google/DateFormat.yml delete mode 100644 ci/vale/Google/Ellipses.yml delete mode 100644 ci/vale/Google/EmDash.yml delete mode 100644 ci/vale/Google/EnDash.yml delete mode 100644 ci/vale/Google/Exclamation.yml delete mode 100644 ci/vale/Google/FirstPerson.yml delete mode 100644 ci/vale/Google/Gender.yml delete mode 100644 ci/vale/Google/GenderBias.yml delete mode 100644 ci/vale/Google/HeadingPunctuation.yml delete mode 100644 ci/vale/Google/Headings.yml delete mode 100644 ci/vale/Google/Hyphens.yml delete mode 100644 ci/vale/Google/Latin.yml delete mode 100644 ci/vale/Google/LyHyphens.yml delete mode 100644 ci/vale/Google/OptionalPlurals.yml delete mode 100644 ci/vale/Google/Ordinal.yml delete mode 100644 ci/vale/Google/OxfordComma.yml delete mode 100644 ci/vale/Google/Parens.yml delete mode 100644 ci/vale/Google/Passive.yml delete mode 100644 ci/vale/Google/Periods.yml delete mode 100644 ci/vale/Google/Quotes.yml delete mode 100644 ci/vale/Google/Ranges.yml delete mode 100644 ci/vale/Google/Semicolons.yml delete mode 100644 ci/vale/Google/Slang.yml delete mode 100644 ci/vale/Google/Spacing.yml delete mode 100644 ci/vale/Google/Spelling.yml delete mode 100644 ci/vale/Google/Units.yml delete mode 100644 ci/vale/Google/Will.yml delete mode 100644 ci/vale/Google/WordList.yml delete mode 100644 ci/vale/Google/meta.json delete mode 100644 ci/vale/Google/vocab.txt delete mode 100644 ci/vale/VyOS/Terminology.yml delete mode 100644 ci/vyos-linter.py diff --git a/.vale b/.vale deleted file mode 100644 index 05e6de93..00000000 --- a/.vale +++ /dev/null @@ -1,16 +0,0 @@ -StylesPath = ci/vale -MinAlertLevel = suggestion - -SkippedScopes = script, style, pre, figure, img, a, code - - -[*.rst] -BasedOnStyles = VyOS - -Google.DateFormat = YES -vale.GenderBias = NO -vale.Hedging = NO -vale.Redundancy = NO -vale.Repetition = YES -vale.Uncomparables = NO -proselint.GenderBias = NO diff --git a/ci/vale/Google/AMPM.yml b/ci/vale/Google/AMPM.yml deleted file mode 100644 index fbdc6e4f..00000000 --- a/ci/vale/Google/AMPM.yml +++ /dev/null @@ -1,9 +0,0 @@ -extends: existence -message: "Use 'AM' or 'PM' (preceded by a space)." -link: 'https://developers.google.com/style/word-list' -level: error -nonword: true -tokens: - - '\d{1,2}[AP]M' - - '\d{1,2} ?[ap]m' - - '\d{1,2} ?[aApP]\.[mM]\.' diff --git a/ci/vale/Google/Acronyms.yml b/ci/vale/Google/Acronyms.yml deleted file mode 100644 index f41af018..00000000 --- a/ci/vale/Google/Acronyms.yml +++ /dev/null @@ -1,64 +0,0 @@ -extends: conditional -message: "Spell out '%s', if it's unfamiliar to the audience." -link: 'https://developers.google.com/style/abbreviations' -level: suggestion -ignorecase: false -# Ensures that the existence of 'first' implies the existence of 'second'. -first: '\b([A-Z]{3,5})\b' -second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' -# ... with the exception of these: -exceptions: - - API - - ASP - - CLI - - CPU - - CSS - - CSV - - DEBUG - - DOM - - DPI - - FAQ - - GCC - - GDB - - GET - - GPU - - GTK - - GUI - - HTML - - HTTP - - HTTPS - - IDE - - JAR - - JSON - - JSX - - LESS - - LLDB - - NET - - NOTE - - NVDA - - OSS - - PATH - - PDF - - PHP - - POST - - RAM - - REPL - - RSA - - SCM - - SCSS - - SDK - - SQL - - SSH - - SSL - - SVG - - TBD - - TCP - - TODO - - URI - - URL - - USB - - UTF - - XML - - XSS - - YAML - - ZIP diff --git a/ci/vale/Google/Colons.yml b/ci/vale/Google/Colons.yml deleted file mode 100644 index 9a4b4b4a..00000000 --- a/ci/vale/Google/Colons.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "'%s' should be in lowercase." -link: 'https://developers.google.com/style/colons' -nonword: true -level: warning -tokens: - - ':\s[A-Z]' diff --git a/ci/vale/Google/Contractions.yml b/ci/vale/Google/Contractions.yml deleted file mode 100644 index 905a39f4..00000000 --- a/ci/vale/Google/Contractions.yml +++ /dev/null @@ -1,28 +0,0 @@ -extends: substitution -message: "Feel free to use '%s' instead of '%s'." -link: 'https://developers.google.com/style/contractions' -level: suggestion -ignorecase: true -swap: - are not: aren't - cannot: can't - could not: couldn't - did not: didn't - do not: don't - does not: doesn't - has not: hasn't - have not: haven't - how is: how's - is not: isn't - it is: it's - should not: shouldn't - that is: that's - they are: they're - was not: wasn't - we are: we're - we have: we've - were not: weren't - what is: what's - when is: when's - where is: where's - will not: won't diff --git a/ci/vale/Google/DateFormat.yml b/ci/vale/Google/DateFormat.yml deleted file mode 100644 index e9d227fa..00000000 --- a/ci/vale/Google/DateFormat.yml +++ /dev/null @@ -1,9 +0,0 @@ -extends: existence -message: "Use 'July 31, 2016' format, not '%s'." -link: 'https://developers.google.com/style/dates-times' -ignorecase: true -level: error -nonword: true -tokens: - - '\d{1,2}(?:\.|/)\d{1,2}(?:\.|/)\d{4}' - - '\d{1,2} (?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)|May|Jun(?:e)|Jul(?:y)|Aug(?:ust)|Sep(?:tember)?|Oct(?:ober)|Nov(?:ember)?|Dec(?:ember)?) \d{4}' diff --git a/ci/vale/Google/Ellipses.yml b/ci/vale/Google/Ellipses.yml deleted file mode 100644 index 436e6177..00000000 --- a/ci/vale/Google/Ellipses.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "In general, don't use an ellipsis." -link: 'https://developers.google.com/style/ellipses' -nonword: true -level: warning -tokens: - - '\.\.\.' diff --git a/ci/vale/Google/EmDash.yml b/ci/vale/Google/EmDash.yml deleted file mode 100644 index c6018db1..00000000 --- a/ci/vale/Google/EmDash.yml +++ /dev/null @@ -1,8 +0,0 @@ -extends: existence -message: "Don't put a space before or after an em dash." -link: 'https://developers.google.com/style/dashes' -nonword: true -level: error -tokens: - - '\s—' - - '—\s' diff --git a/ci/vale/Google/EnDash.yml b/ci/vale/Google/EnDash.yml deleted file mode 100644 index 194876aa..00000000 --- a/ci/vale/Google/EnDash.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Use an em dash ('—') instead of '–'." -link: 'https://developers.google.com/style/dashes' -nonword: true -level: error -tokens: - - '–' diff --git a/ci/vale/Google/Exclamation.yml b/ci/vale/Google/Exclamation.yml deleted file mode 100644 index c4db380b..00000000 --- a/ci/vale/Google/Exclamation.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Don't use exclamation points in text." -link: 'https://developers.google.com/style/exclamation-points' -nonword: true -level: error -tokens: - - '!' diff --git a/ci/vale/Google/FirstPerson.yml b/ci/vale/Google/FirstPerson.yml deleted file mode 100644 index d2290611..00000000 --- a/ci/vale/Google/FirstPerson.yml +++ /dev/null @@ -1,11 +0,0 @@ -extends: existence -message: "Avoid first-person pronouns such as '%s'." -link: 'https://developers.google.com/style/pronouns#personal-pronouns' -ignorecase: true -level: warning -nonword: true -tokens: - - (?:^|\s)I\s - - \bme\b - - \bus\b - - \bours\b diff --git a/ci/vale/Google/Gender.yml b/ci/vale/Google/Gender.yml deleted file mode 100644 index c8486181..00000000 --- a/ci/vale/Google/Gender.yml +++ /dev/null @@ -1,9 +0,0 @@ -extends: existence -message: "Don't use '%s' as a gender-neutral pronoun." -link: 'https://developers.google.com/style/pronouns#gender-neutral-pronouns' -level: error -ignorecase: true -tokens: - - he/she - - s/he - - \(s\)he diff --git a/ci/vale/Google/GenderBias.yml b/ci/vale/Google/GenderBias.yml deleted file mode 100644 index 261cfb66..00000000 --- a/ci/vale/Google/GenderBias.yml +++ /dev/null @@ -1,45 +0,0 @@ -extends: substitution -message: "Consider using '%s' instead of '%s'." -link: 'https://developers.google.com/style/inclusive-documentation' -ignorecase: true -level: error -swap: - (?:alumna|alumnus): graduate - (?:alumnae|alumni): graduates - air(?:m[ae]n|wom[ae]n): pilot(s) - anchor(?:m[ae]n|wom[ae]n): anchor(s) - authoress: author - camera(?:m[ae]n|wom[ae]n): camera operator(s) - chair(?:m[ae]n|wom[ae]n): chair(s) - congress(?:m[ae]n|wom[ae]n): member(s) of congress - door(?:m[ae]|wom[ae]n): concierge(s) - draft(?:m[ae]n|wom[ae]n): drafter(s) - fire(?:m[ae]n|wom[ae]n): firefighter(s) - fisher(?:m[ae]n|wom[ae]n): fisher(s) - fresh(?:m[ae]n|wom[ae]n): first-year student(s) - garbage(?:m[ae]n|wom[ae]n): waste collector(s) - lady lawyer: lawyer - ladylike: courteous - landlord: building manager - mail(?:m[ae]n|wom[ae]n): mail carriers - man and wife: husband and wife - man enough: strong enough - mankind: human kind - manmade: manufactured - manpower: personnel - men and girls: men and women - middle(?:m[ae]n|wom[ae]n): intermediary - news(?:m[ae]n|wom[ae]n): journalist(s) - ombuds(?:man|woman): ombuds - oneupmanship: upstaging - poetess: poet - police(?:m[ae]n|wom[ae]n): police officer(s) - repair(?:m[ae]n|wom[ae]n): technician(s) - sales(?:m[ae]n|wom[ae]n): salesperson or sales people - service(?:m[ae]n|wom[ae]n): soldier(s) - steward(?:ess)?: flight attendant - tribes(?:m[ae]n|wom[ae]n): tribe member(s) - waitress: waiter - woman doctor: doctor - woman scientist[s]?: scientist(s) - work(?:m[ae]n|wom[ae]n): worker(s) diff --git a/ci/vale/Google/HeadingPunctuation.yml b/ci/vale/Google/HeadingPunctuation.yml deleted file mode 100644 index 5c39abbf..00000000 --- a/ci/vale/Google/HeadingPunctuation.yml +++ /dev/null @@ -1,8 +0,0 @@ -extends: existence -message: "Don't put a period at the end of a heading." -link: 'https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings' -nonword: true -level: warning -scope: heading -tokens: - - '[a-z0-9][.](?:\s|$)' diff --git a/ci/vale/Google/Headings.yml b/ci/vale/Google/Headings.yml deleted file mode 100644 index 5afb968d..00000000 --- a/ci/vale/Google/Headings.yml +++ /dev/null @@ -1,26 +0,0 @@ -extends: capitalization -message: "'%s' should use sentence-style capitalization." -link: 'https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings' -level: warning -scope: heading -match: $sentence -exceptions: - - Azure - - CLI - - Code - - Cosmos - - Docker - - Emmet - - I - - Kubernetes - - Linux - - macOS - - Marketplace - - MongoDB - - REPL - - Studio - - TypeScript - - URLs - - Visual - - VS - - Windows diff --git a/ci/vale/Google/Hyphens.yml b/ci/vale/Google/Hyphens.yml deleted file mode 100644 index f9779637..00000000 --- a/ci/vale/Google/Hyphens.yml +++ /dev/null @@ -1,8 +0,0 @@ -extends: existence -message: "Don't place a space on either side of a hyphen (unless it's suspended)." -link: 'https://developers.google.com/style/hyphens' -level: warning -nonword: true -tokens: - - '\s-' - - '-\s' diff --git a/ci/vale/Google/Latin.yml b/ci/vale/Google/Latin.yml deleted file mode 100644 index f032b349..00000000 --- a/ci/vale/Google/Latin.yml +++ /dev/null @@ -1,9 +0,0 @@ -extends: substitution -message: "Use '%s' instead of '%s'." -link: 'https://developers.google.com/style/abbreviations' -ignorecase: true -level: error -nonword: true -swap: - '\b(?:eg|e\.g\.)[\s,]': for example - '\b(?:ie|i\.e\.)[\s,]': that is diff --git a/ci/vale/Google/LyHyphens.yml b/ci/vale/Google/LyHyphens.yml deleted file mode 100644 index d5b6a942..00000000 --- a/ci/vale/Google/LyHyphens.yml +++ /dev/null @@ -1,8 +0,0 @@ -extends: existence -message: "'%s' doesn't need a hyphen." -link: 'https://developers.google.com/style/hyphens' -level: error -ignorecase: false -nonword: true -tokens: - - '\s[^\s-]+ly-' diff --git a/ci/vale/Google/OptionalPlurals.yml b/ci/vale/Google/OptionalPlurals.yml deleted file mode 100644 index 7058932f..00000000 --- a/ci/vale/Google/OptionalPlurals.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Don't use plurals in parentheses such as in '%s'." -link: 'https://developers.google.com/style/plurals-parentheses' -level: error -nonword: true -tokens: - - '\b\w+\(s\)' diff --git a/ci/vale/Google/Ordinal.yml b/ci/vale/Google/Ordinal.yml deleted file mode 100644 index 8c429e0f..00000000 --- a/ci/vale/Google/Ordinal.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Spell out all ordinal numbers ('%s') in text." -link: 'https://developers.google.com/style/numbers' -level: error -nonword: true -tokens: - - \d+(?:st|th|rd) diff --git a/ci/vale/Google/OxfordComma.yml b/ci/vale/Google/OxfordComma.yml deleted file mode 100644 index 98b07113..00000000 --- a/ci/vale/Google/OxfordComma.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Use the Oxford comma in '%s'." -link: 'https://developers.google.com/style/commas' -scope: sentence -level: warning -tokens: - - '(?:[^,]+,){1,}\s\w+\sand' diff --git a/ci/vale/Google/Parens.yml b/ci/vale/Google/Parens.yml deleted file mode 100644 index 3b8711d0..00000000 --- a/ci/vale/Google/Parens.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Use parentheses judiciously." -link: 'https://developers.google.com/style/parentheses' -nonword: true -level: suggestion -tokens: - - '\(.+\)' diff --git a/ci/vale/Google/Passive.yml b/ci/vale/Google/Passive.yml deleted file mode 100644 index 3265890e..00000000 --- a/ci/vale/Google/Passive.yml +++ /dev/null @@ -1,184 +0,0 @@ -extends: existence -link: 'https://developers.google.com/style/voice' -message: "In general, use active voice instead of passive voice ('%s')." -ignorecase: true -level: suggestion -raw: - - \b(am|are|were|being|is|been|was|be)\b\s* -tokens: - - '[\w]+ed' - - awoken - - beat - - become - - been - - begun - - bent - - beset - - bet - - bid - - bidden - - bitten - - bled - - blown - - born - - bought - - bound - - bred - - broadcast - - broken - - brought - - built - - burnt - - burst - - cast - - caught - - chosen - - clung - - come - - cost - - crept - - cut - - dealt - - dived - - done - - drawn - - dreamt - - driven - - drunk - - dug - - eaten - - fallen - - fed - - felt - - fit - - fled - - flown - - flung - - forbidden - - foregone - - forgiven - - forgotten - - forsaken - - fought - - found - - frozen - - given - - gone - - gotten - - ground - - grown - - heard - - held - - hidden - - hit - - hung - - hurt - - kept - - knelt - - knit - - known - - laid - - lain - - leapt - - learnt - - led - - left - - lent - - let - - lighted - - lost - - made - - meant - - met - - misspelt - - mistaken - - mown - - overcome - - overdone - - overtaken - - overthrown - - paid - - pled - - proven - - put - - quit - - read - - rid - - ridden - - risen - - run - - rung - - said - - sat - - sawn - - seen - - sent - - set - - sewn - - shaken - - shaven - - shed - - shod - - shone - - shorn - - shot - - shown - - shrunk - - shut - - slain - - slept - - slid - - slit - - slung - - smitten - - sold - - sought - - sown - - sped - - spent - - spilt - - spit - - split - - spoken - - spread - - sprung - - spun - - stolen - - stood - - stridden - - striven - - struck - - strung - - stuck - - stung - - stunk - - sung - - sunk - - swept - - swollen - - sworn - - swum - - swung - - taken - - taught - - thought - - thrived - - thrown - - thrust - - told - - torn - - trodden - - understood - - upheld - - upset - - wed - - wept - - withheld - - withstood - - woken - - won - - worn - - wound - - woven - - written - - wrung diff --git a/ci/vale/Google/Periods.yml b/ci/vale/Google/Periods.yml deleted file mode 100644 index d24a6a6c..00000000 --- a/ci/vale/Google/Periods.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Don't use periods with acronyms or initialisms such as '%s'." -link: 'https://developers.google.com/style/abbreviations' -level: error -nonword: true -tokens: - - '\b(?:[A-Z]\.){3,}' diff --git a/ci/vale/Google/Quotes.yml b/ci/vale/Google/Quotes.yml deleted file mode 100644 index 3cb6f1ab..00000000 --- a/ci/vale/Google/Quotes.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Commas and periods go inside quotation marks." -link: 'https://developers.google.com/style/quotation-marks' -level: error -nonword: true -tokens: - - '"[^"]+"[.,?]' diff --git a/ci/vale/Google/Ranges.yml b/ci/vale/Google/Ranges.yml deleted file mode 100644 index 3ec045e7..00000000 --- a/ci/vale/Google/Ranges.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Don't add words such as 'from' or 'between' to describe a range of numbers." -link: 'https://developers.google.com/style/hyphens' -nonword: true -level: warning -tokens: - - '(?:from|between)\s\d+\s?-\s?\d+' diff --git a/ci/vale/Google/Semicolons.yml b/ci/vale/Google/Semicolons.yml deleted file mode 100644 index bb8b85b4..00000000 --- a/ci/vale/Google/Semicolons.yml +++ /dev/null @@ -1,8 +0,0 @@ -extends: existence -message: "Use semicolons judiciously." -link: 'https://developers.google.com/style/semicolons' -nonword: true -scope: sentence -level: suggestion -tokens: - - ';' diff --git a/ci/vale/Google/Slang.yml b/ci/vale/Google/Slang.yml deleted file mode 100644 index 63f4c248..00000000 --- a/ci/vale/Google/Slang.yml +++ /dev/null @@ -1,11 +0,0 @@ -extends: existence -message: "Don't use internet slang abbreviations such as '%s'." -link: 'https://developers.google.com/style/abbreviations' -ignorecase: true -level: error -tokens: - - 'tl;dr' - - ymmv - - rtfm - - imo - - fwiw diff --git a/ci/vale/Google/Spacing.yml b/ci/vale/Google/Spacing.yml deleted file mode 100644 index 5f209a9f..00000000 --- a/ci/vale/Google/Spacing.yml +++ /dev/null @@ -1,8 +0,0 @@ -extends: existence -message: "'%s' should have one space." -link: 'https://developers.google.com/style/sentence-spacing' -level: error -nonword: true -tokens: - - '[.?!] {2,}[A-Z]' - - '[.?!][A-Z]' diff --git a/ci/vale/Google/Spelling.yml b/ci/vale/Google/Spelling.yml deleted file mode 100644 index 57acb884..00000000 --- a/ci/vale/Google/Spelling.yml +++ /dev/null @@ -1,8 +0,0 @@ -extends: existence -message: "In general, use American spelling instead of '%s'." -link: 'https://developers.google.com/style/spelling' -ignorecase: true -level: warning -tokens: - - '(?:\w+)nised?' - - '(?:\w+)logue' diff --git a/ci/vale/Google/Units.yml b/ci/vale/Google/Units.yml deleted file mode 100644 index 220de3e9..00000000 --- a/ci/vale/Google/Units.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Put a nonbreaking space between the number and the unit in '%s'." -link: 'https://developers.google.com/style/units-of-measure' -nonword: true -level: error -tokens: - - \d+(?:GB|TB|MB) diff --git a/ci/vale/Google/Will.yml b/ci/vale/Google/Will.yml deleted file mode 100644 index 128a9183..00000000 --- a/ci/vale/Google/Will.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Avoid using '%s'." -link: 'https://developers.google.com/style/tense' -ignorecase: true -level: warning -tokens: - - will diff --git a/ci/vale/Google/WordList.yml b/ci/vale/Google/WordList.yml deleted file mode 100644 index d5d6bea5..00000000 --- a/ci/vale/Google/WordList.yml +++ /dev/null @@ -1,79 +0,0 @@ -extends: substitution -message: "Use %s instead of '%s'." -link: 'https://developers.google.com/style/word-list' -level: warning -ignorecase: false -swap: - '(?:API Console|dev|developer) key': "'API key'" - '(?:cell ?phone|smart ?phone)': "'phone' or 'mobile phone'" - '(?:dev|developer|APIs) console': "'API console'" - '(?:e-mail|Email|E-mail)': "'email'" - '(?:file ?path|path ?name)': "'path'" - '(?:kill|terminate)': "'stop', 'exit', 'cancel', or 'end'" - '(?:OAuth ?2|Oauth)': "'OAuth 2.0'" - '(?:ok|Okay)': "'OK' or 'okay'" - '(?:WiFi|wifi)': "'Wi-Fi'" - '[\.]+apk': "'APK'" - '3\-D': "'3D'" - 'Google (?:I\-O|IO)': "'Google I/O'" - 'tap (?:&|and) hold': "'touch & hold'" - 'un(?:check|select)': "'clear'" - abort: "'stop', 'exit', 'cancel' or 'end'" - above: "'preceding'" - account name: "'username'" - action bar: "'app bar'" - admin: "'administrator'" - Ajax: "'AJAX'" - Android device: "'Android-powered device'" - android: "'Android'" - API explorer: "'APIs Explorer'" - application: "'app'" - approx\.: "'approximately'" - authN: "'authentication'" - authZ: "'authorization'" - autoupdate: "'automatically update'" - cellular data: "'mobile data'" - cellular network: "'mobile network'" - chapter: "'documents', 'pages', 'sections'" - check box: "'checkbox'" - check: "'select'" - CLI: "'command-line tool'" - click on: "'click' or 'click in'" - Cloud: "'Google Cloud Platform' or 'GCP'" - Container Engine: "'Kubernetes Engine'" - content type: "'media type'" - curated roles: "'predefined roles'" - data are: "'data is'" - Developers Console: "'Google API Console' or 'API Console'" - disabled?: "'turn off' or 'off'" - ephemeral IP address: "'ephemeral external IP address'" - fewer data: "'less data'" - file name: "'filename'" - firewalls: "'firewall rules'" - functionality: "'capability' or 'feature'" - Google account: "'Google Account'" - Google accounts: "'Google Accounts'" - Googling: "'search with Google'" - grayed-out: "'unavailable'" - HTTPs: "'HTTPS'" - in order to: "'to'" - ingest: "'import' or 'load'" - k8s: "'Kubernetes'" - long press: "'touch & hold'" - network IP address: "'internal IP address'" - omnibox: "'address bar'" - open-source: "'open source'" - overview screen: "'recents screen'" - regex: "'regular expression'" - SHA1: "'SHA-1' or 'HAS-SHA1'" - sign into: "'sign in to'" - sign-?on: "'single sign-on'" - static IP address: "'static external IP address'" - stylesheet: "'style sheet'" - synch: "'sync'" - tablename: "'table name'" - tablet: "'device'" - touch: "'tap'" - url: "'URL'" - vs\.: "'versus'" - World Wide Web: "'web'" diff --git a/ci/vale/Google/meta.json b/ci/vale/Google/meta.json deleted file mode 100644 index 3ae5fb21..00000000 --- a/ci/vale/Google/meta.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "author": "Joseph Kato", - "description": "A Vale-compatible implementation of the Microsoft Writing Style Guide.", - "email": "support@errata.ai", - "lang": "en", - "url": "https://github.com/errata-ai/Google/releases/latest/download/Google.zip", - "feed": "https://github.com/errata-ai/Google/releases.atom", - "issues": "https://github.com/errata-ai/Google/issues/new", - "license": "MIT", - "name": "Google", - "sources": [ - "https://developers.google.com/style/" - ], - "vale_version": ">=1.0.0", - "coverage": 0.0 -} diff --git a/ci/vale/Google/vocab.txt b/ci/vale/Google/vocab.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/ci/vale/VyOS/Terminology.yml b/ci/vale/VyOS/Terminology.yml deleted file mode 100644 index cd0c5089..00000000 --- a/ci/vale/VyOS/Terminology.yml +++ /dev/null @@ -1,9 +0,0 @@ -extends: substitution -message: Prefer '%s' over '%s' -ignorecase: false -level: error -swap: - vyos: VyOS - Vyos: VyOS - VYOS: VyOS - Gre: GRE \ No newline at end of file diff --git a/ci/vyos-linter.py b/ci/vyos-linter.py deleted file mode 100644 index 3bf65484..00000000 --- a/ci/vyos-linter.py +++ /dev/null @@ -1,117 +0,0 @@ -import os -import re -import ipaddress - -IPV4SEG = r'(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])' -IPV4ADDR = r'(?:(?:' + IPV4SEG + r'\.){3,3}' + IPV4SEG + r')' -IPV6SEG = r'(?:(?:[0-9a-fA-F]){1,4})' -IPV6GROUPS = ( - r'(?:' + IPV6SEG + r':){7,7}' + IPV6SEG, # 1:2:3:4:5:6:7:8 - r'(?:\s' + IPV6SEG + r':){1,7}:', # 1:: 1:2:3:4:5:6:7:: - r'(?:' + IPV6SEG + r':){1,6}:' + IPV6SEG, # 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8 - r'(?:' + IPV6SEG + r':){1,5}(?::' + IPV6SEG + r'){1,2}', # 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8 - r'(?:' + IPV6SEG + r':){1,4}(?::' + IPV6SEG + r'){1,3}', # 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8 - r'(?:' + IPV6SEG + r':){1,3}(?::' + IPV6SEG + r'){1,4}', # 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8 - r'(?:' + IPV6SEG + r':){1,2}(?::' + IPV6SEG + r'){1,5}', # 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8 - IPV6SEG + r':(?:(?::' + IPV6SEG + r'){1,6})', # 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8 - r':(?:(?::' + IPV6SEG + r'){1,7}|:)', # ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 :: - r'fe80:(?::' + IPV6SEG + r'){0,4}%[0-9a-zA-Z]{1,}', # fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index) - r'::(?:ffff(?::0{1,4}){0,1}:){0,1}[^\s:]' + IPV4ADDR, # ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses) - r'(?:' + IPV6SEG + r':){1,4}:[^\s:]' + IPV4ADDR, # 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address) -) -IPV6ADDR = '|'.join(['(?:{})'.format(g) for g in IPV6GROUPS[::-1]]) # Reverse rows for greedy match - -MAC = r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})' - -NUMBER = r"([\s']\d+[\s'])" - - -def lint_mac(cnt, line): - mac = re.search(MAC, line, re.I) - if mac is not None: - mac = mac.group() - u_mac = re.search(r'((00)[:-](53)([:-][0-9A-F]{2}){4})', mac, re.I) - m_mac = re.search(r'((90)[:-](10)([:-][0-9A-F]{2}){4})', mac, re.I) - if u_mac is None and m_mac is None: - return f"MAC-Address Error Line {cnt}: {mac}" - - -def lint_ipv4(cnt, line): - ip = re.search(IPV4ADDR, line, re.I) - if ip is not None: - ip = ipaddress.ip_address(ip.group().strip(' ')) - # https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.is_private - if ip.is_private is False and ip.is_multicast is False: - return f"IPv4 Error Line {cnt}: {ip}" - - -def lint_ipv6(cnt, line): - ip = re.search(IPV6ADDR, line, re.I) - if ip is not None: - ip = ipaddress.ip_address(ip.group().strip(' ')) - # https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.is_private - if ip.is_private is False and ip.is_multicast is False: - return f"IPv6 Error Line {cnt}: {ip}" - - -def lint_AS(cnt, line): - number = re.search(NUMBER, line, re.I) - if number: - pass - # find a way to detect AS numbers - - -def lint_linelen(cnt, line): - if len(line) > 80: - return f"Line {cnt} too long: len={len(line)}" - - -def handle_file(path, file): - errors = [] - path = '/'.join(path) - filepath = f"{path}/{file}" - try: - with open(filepath) as fp: - line = fp.readline() - cnt = 1 - while line: - err_mac = lint_mac(cnt, line.strip()) - err_ip4 = lint_ipv4(cnt, line.strip()) - err_ip6 = lint_ipv6(cnt, line.strip()) - err_len = lint_linelen(cnt, line.strip()) - if err_mac: - errors.append(err_mac) - if err_ip4: - errors.append(err_ip4) - if err_ip6: - errors.append(err_ip6) - if err_len: - errors.append(err_len) - line = fp.readline() - cnt += 1 - finally: - fp.close() - - if len(errors) > 0: - print(f"File: {filepath}") - for error in errors: - print(error) - print('') - return False - - -def main(): - bool_error = True - # TODO: path and/or files via cli arg - for root, dirs, files in os.walk("../docs"): - path = root.split(os.sep) - for file in files: - if file[-4:] == ".rst": - if handle_file(path, file) is False: - bool_error = False - return bool_error - - -if __name__ == "__main__": - if main() is False: - exit(1) From de9eaec2cf26bb67738d953fbc87a3f3320aa3d7 Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 22:12:04 +0100 Subject: [PATCH 05/28] prepare coverage.rst --- docs/_ext/testcoverage.py | 351 ++++++++++++++++++++++++++++++++++++++ docs/_ext/vyos.py | 264 ++++++++++++++++++++++++---- docs/coverage.rst | 43 +++++ 3 files changed, 626 insertions(+), 32 deletions(-) create mode 100644 docs/_ext/testcoverage.py create mode 100644 docs/coverage.rst diff --git a/docs/_ext/testcoverage.py b/docs/_ext/testcoverage.py new file mode 100644 index 00000000..70714d6b --- /dev/null +++ b/docs/_ext/testcoverage.py @@ -0,0 +1,351 @@ +''' +generate json with all commands from xml for vyos documentation coverage + +''' + + +import sys +import os +import json +import re +import logging + +from io import BytesIO +from lxml import etree as ET +import shutil + +default_constraint_err_msg = "Invalid value" +validator_dir = "" + + +input_data = [ + { + "kind": "cfgcmd", + "input_dir": "_include/vyos-1x/interface-definitions/", + "schema_file": "_include/vyos-1x/schema/interface_definition.rng", + "files": [] + }, + { + "kind": "opcmd", + "input_dir": "_include/vyos-1x/op-mode-definitions/", + "schema_file": "_include/vyos-1x/schema/op-mode-definition.rng", + "files": [] + } +] + +node_data = { + 'cfgcmd': {}, + 'opcmd': {}, +} + +def get_properties(p): + props = {} + props['valueless'] = False + + try: + if p.find("valueless") is not None: + props['valueless'] = True + except: + pass + + if p is None: + return props + + # Get the help string + try: + props["help"] = p.find("help").text + except: + pass + + # Get value help strings + try: + vhe = p.findall("valueHelp") + vh = [] + for v in vhe: + vh.append( (v.find("format").text, v.find("description").text) ) + props["val_help"] = vh + except: + props["val_help"] = [] + + # Get the constraint statements + error_msg = default_constraint_err_msg + # Get the error message if it's there + try: + error_msg = p.find("constraintErrorMessage").text + except: + pass + + + vce = p.find("constraint") + vc = [] + if vce is not None: + # The old backend doesn't support multiple validators in OR mode + # so we emulate it + + regexes = [] + regex_elements = vce.findall("regex") + if regex_elements is not None: + regexes = list(map(lambda e: e.text.strip(), regex_elements)) + if "" in regexes: + print("Warning: empty regex, node will be accepting any value") + + validator_elements = vce.findall("validator") + validators = [] + if validator_elements is not None: + for v in validator_elements: + v_name = os.path.join(validator_dir, v.get("name")) + + # XXX: lxml returns None for empty arguments + v_argument = None + try: + v_argument = v.get("argument") + except: + pass + if v_argument is None: + v_argument = "" + + validators.append("{0} {1}".format(v_name, v_argument)) + + + regex_args = " ".join(map(lambda s: "--regex \\\'{0}\\\'".format(s), regexes)) + validator_args = " ".join(map(lambda s: "--exec \\\"{0}\\\"".format(s), validators)) + validator_script = '${vyos_libexec_dir}/validate-value.py' + validator_string = "exec \"{0} {1} {2} --value \\\'$VAR(@)\\\'\"; \"{3}\"".format(validator_script, regex_args, validator_args, error_msg) + + props["constraint"] = validator_string + + # Get the completion help strings + try: + che = p.findall("completionHelp") + ch = "" + for c in che: + scripts = c.findall("script") + paths = c.findall("path") + lists = c.findall("list") + + # Current backend doesn't support multiple allowed: tags + # so we get to emulate it + comp_exprs = [] + for i in lists: + comp_exprs.append("echo \"{0}\"".format(i.text)) + for i in paths: + comp_exprs.append("/bin/cli-shell-api listNodes {0}".format(i.text)) + for i in scripts: + comp_exprs.append("sh -c \"{0}\"".format(i.text)) + comp_help = " && ".join(comp_exprs) + props["comp_help"] = comp_help + except: + props["comp_help"] = [] + + # Get priority + try: + props["priority"] = p.find("priority").text + except: + pass + + # Get "multi" + if p.find("multi") is not None: + props["multi"] = True + + # Get "valueless" + if p.find("valueless") is not None: + props["valueless"] = True + + return props + +def process_node(n, f): + + props_elem = n.find("properties") + children = n.find("children") + command = n.find("command") + children_nodes = [] + owner = n.get("owner") + node_type = n.tag + + name = n.get("name") + props = get_properties(props_elem) + + if node_type != "node": + if "valueless" not in props.keys(): + props["type"] = "txt" + if node_type == "tagNode": + props["tag"] = "True" + + if node_type == "node" and children is not None: + inner_nodes = children.iterfind("*") + index_child = 0 + for inner_n in inner_nodes: + children_nodes.append(process_node(inner_n, f)) + index_child = index_child + 1 + + if node_type == "tagNode" and children is not None: + inner_nodes = children.iterfind("*") + index_child = 0 + for inner_n in inner_nodes: + children_nodes.append(process_node(inner_n, f)) + index_child = index_child + 1 + else: + # This is a leaf node + pass + + if command is not None: + test_command = True + else: + test_command = False + node = { + 'name': name, + 'type': node_type, + 'children': children_nodes, + 'props': props, + 'command': test_command, + 'filename': f + } + return node + + + +def create_commands(data, parent_list=[], level=0): + result = [] + command = { + 'name': [], + 'help': None, + 'tag_help': [], + 'level': level, + 'no_childs': False, + 'filename': None + } + command['filename'] = data['filename'] + command['name'].extend(parent_list) + command['name'].append(data['name']) + + if data['type'] == 'tagNode': + command['name'].append("<" + data['name'] + ">") + + if 'val_help' in data['props'].keys(): + for val_help in data['props']['val_help']: + command['tag_help'].append(val_help) + + if len(data['children']) == 0: + command['no_childs'] = True + + if data['command']: + command['no_childs'] = True + + try: + help_text = data['props']['help'] + command['help'] = re.sub(r"[\n\t]*", "", help_text) + + except: + command['help'] = "" + + command['valueless'] = data['props']['valueless'] + + if 'children' in data.keys(): + children_bool = True + for child in data['children']: + result.extend(create_commands(child, command['name'], level + 1)) + + if command['no_childs']: + result.append(command) + + + + return result + + +def include_file(line, input_dir): + string = "" + if "#include ','',cmd) + cmd = re.sub('\[\S\]','',cmd) + cmd = re.sub('\s+','',cmd) + return cmd + +def build_row(app, fromdocname, rowdata): + row = nodes.row() + for cell in rowdata: + entry = nodes.entry() + row += entry + if isinstance(cell, list): + for item in cell: + if isinstance(item, dict): + entry += process_cmd_node(app, item, fromdocname, '') + else: + entry += nodes.paragraph(text=item) + elif isinstance(cell, bool): + if cell: + entry += nodes.paragraph(text="") + entry['classes'] = ['coverage-ok'] + else: + entry += nodes.paragraph(text="") + entry['classes'] = ['coverage-fail'] + else: + entry += nodes.paragraph(text=cell) + return row + + + +def process_coverage(app, fromdocname, doccmd, xmlcmd, cli_type): + coverage_list = {} + int_docs = 0 + int_xml = 0 + for cmd in doccmd: + coverage_item = { + 'doccmd': None, + 'xmlcmd': None, + 'doccmd_item': None, + 'xmlcmd_item': None, + 'indocs': False, + 'inxml': False, + 'xmlfilename': None + } + coverage_item['doccmd'] = cmd['cmd'] + coverage_item['doccmd_item'] = cmd + coverage_item['indocs'] = True + int_docs += 1 + coverage_list[strip_cmd(cmd['cmd'])] = dict(coverage_item) + + for cmd in xmlcmd: + + strip = strip_cmd(cmd['cmd']) + if strip not in coverage_list.keys(): + coverage_item = { + 'doccmd': None, + 'xmlcmd': None, + 'doccmd_item': None, + 'xmlcmd_item': None, + 'indocs': False, + 'inxml': False, + 'xmlfilename': None + } + coverage_item['xmlcmd'] = cmd['cmd'] + coverage_item['xmlcmd_item'] = cmd + coverage_item['inxml'] = True + coverage_item['xmlfilename'] = cmd['filename'] + int_xml += 1 + coverage_list[strip] = dict(coverage_item) + else: + #print("===BEGIN===") + #print(cmd) + #print(coverage_list[strip]) + #print(strip) + #print("===END====") + coverage_list[strip]['xmlcmd'] = cmd['cmd'] + coverage_list[strip]['xmlcmd_item'] = cmd + coverage_list[strip]['inxml'] = True + coverage_list[strip]['xmlfilename'] = cmd['filename'] + int_xml += 1 + + + + + table = nodes.table() + tgroup = nodes.tgroup(cols=3) + table += tgroup + + header = (f'{int_docs}/{len(coverage_list)} in Docs', f'{int_xml}/{len(coverage_list)} in XML', 'Command') + colwidths = (1, 1, 8) + table = nodes.table() + tgroup = nodes.tgroup(cols=len(header)) + table += tgroup + for colwidth in colwidths: + tgroup += nodes.colspec(colwidth=colwidth) + thead = nodes.thead() + tgroup += thead + thead += build_row(app, fromdocname, header) + tbody = nodes.tbody() + tgroup += tbody + for entry in sorted(coverage_list): + body_text_list = [] + if coverage_list[entry]['indocs']: + body_text_list.append(coverage_list[entry]['doccmd_item']) + else: + body_text_list.append('Not documented yet') + + if coverage_list[entry]['inxml']: + body_text_list.append("------------------") + body_text_list.append(str(coverage_list[entry]['xmlfilename']) + ":") + body_text_list.append(coverage_list[entry]['xmlcmd']) + else: + body_text_list.append('Nothing found in XML Definitions') + + + tbody += build_row(app, fromdocname, + ( + coverage_list[entry]['indocs'], + coverage_list[entry]['inxml'], + body_text_list + ) + ) + + return table + +def process_cmd_node(app, cmd, fromdocname, cli_type): para = nodes.paragraph() newnode = nodes.reference('', '') innernode = cmd['cmdnode'] @@ -401,21 +577,45 @@ def process_cmd_node(app, cmd, fromdocname): def process_cmd_nodes(app, doctree, fromdocname): - env = app.builder.env + try: + env = app.builder.env + + for node in doctree.traverse(CfgcmdList): + content = [] + if node.attributes['coverage']: + node.replace_self( + process_coverage( + app, + fromdocname, + env.vyos_cfgcmd, + app.config.vyos_working_commands['cfgcmd'], + 'cfgcmd' + ) + ) + else: + for cmd in sorted(env.vyos_cfgcmd, key=lambda i: i['cmd']): + content.append(process_cmd_node(app, cmd, fromdocname, 'cfgcmd')) + node.replace_self(content) + + for node in doctree.traverse(OpcmdList): + content = [] + if node.attributes['coverage']: + node.replace_self( + process_coverage( + app, + fromdocname, + env.vyos_opcmd, + app.config.vyos_working_commands['opcmd'], + 'opcmd' + ) + ) + else: + for cmd in sorted(env.vyos_opcmd, key=lambda i: i['cmd']): + content.append(process_cmd_node(app, cmd, fromdocname, 'opcmd')) + node.replace_self(content) - for node in doctree.traverse(CfgcmdList): - content = [] - - for cmd in sorted(env.vyos_cfgcmd, key=lambda i: i['cmd']): - content.append(process_cmd_node(app, cmd, fromdocname)) - node.replace_self(content) - - for node in doctree.traverse(OpcmdList): - content = [] - - for cmd in sorted(env.vyos_opcmd, key=lambda i: i['cmd']): - content.append(process_cmd_node(app, cmd, fromdocname)) - node.replace_self(content) + except Exception as inst: + print(inst) def vytask_role(name, rawtext, text, lineno, inliner, options={}, content=[]): @@ -430,4 +630,4 @@ def vytask_role(name, rawtext, text, lineno, inliner, options={}, content=[]): def cmd_role(name, rawtext, text, lineno, inliner, options={}, content=[]): node = nodes.literal(text, text) - return [node], [] + return [node], [] \ No newline at end of file diff --git a/docs/coverage.rst b/docs/coverage.rst new file mode 100644 index 00000000..f003f9ff --- /dev/null +++ b/docs/coverage.rst @@ -0,0 +1,43 @@ +:orphan: + +######## +Coverage +######## + +Overview over all commands, which are documented in the ``.. cfgcmd::`` or ``.. opcmd::`` Directives. + +| The build process take all xml definition files from `vyos-1x `_ and extract each leaf command or executable command. +| After this the commands are compare and shown in the follwoing two tables. +| The script compare only the fixed part of a command. All varables or values will be erase and then compare: + +for example there are these two commands: + + * documentation: ``interfaces ethernet address
``` + * xml: ``interface ethernet address
`` + +Now the script earse all in between ``<`` and ``>`` and simply compare the strings. + +**There are 2 kind of problems:** + +| ``Not documented yet`` +| A XML command are not found in ``.. cfgcmd::`` or ``.. opcmd::`` Commands +| The command should be documented + +| ``Nothing found in XML Definitions``: +| ``.. cfgcmd::`` or ``.. opcmd::`` Command are not found in a XML command +| Maybe the command where changed in the XML Definition, or the feature is not anymore in VyOS +| Some commands are not yet translated to XML + + +Configuration Commands +====================== + +.. cfgcmdlist:: + :show-coverage: + + +Operational Commands +==================== + +.. opcmdlist:: + :show-coverage: \ No newline at end of file From bd631530b21be71277f8e0d5545f087d5c4d49cb Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 22:20:53 +0100 Subject: [PATCH 06/28] remove submodule --- .gitmodules | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d3d92138..00000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "docs/_include/vyos-1x"] - path = docs/_include/vyos-1x - url = https://github.com/vyos/vyos-1x - branch = current From d4863cc15079682634ecca21dd87442ae3cb5666 Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 22:32:45 +0100 Subject: [PATCH 07/28] add vyos-1x submodule --- .gitmodules | 4 ++++ docs/_include/vyos-1x | 1 + 2 files changed, 5 insertions(+) create mode 100644 .gitmodules create mode 160000 docs/_include/vyos-1x diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..d3d92138 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "docs/_include/vyos-1x"] + path = docs/_include/vyos-1x + url = https://github.com/vyos/vyos-1x + branch = current diff --git a/docs/_include/vyos-1x b/docs/_include/vyos-1x new file mode 160000 index 00000000..64d6e689 --- /dev/null +++ b/docs/_include/vyos-1x @@ -0,0 +1 @@ +Subproject commit 64d6e689a8274845a49e6931eda6cda04615de42 From bee2a84c89fc24a54b3687027ff0ed9dd951082f Mon Sep 17 00:00:00 2001 From: rebortg Date: Thu, 26 Nov 2020 22:37:40 +0100 Subject: [PATCH 08/28] increase version --- docs/conf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index bb32aa33..4bb2da3c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,10 +26,10 @@ copyright = u'2020, VyOS maintainers and contributors' author = u'VyOS maintainers and contributors' # The short X.Y version -version = u'1.3' +version = u'1.4' # The full version, including alpha/beta/rc tags -release = u'1.3.x (equuleus)' +release = u'1.4.x (sagitta)' # -- General configuration --------------------------------------------------- @@ -70,7 +70,7 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path . -exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store', '_include/vyos-1x'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' From c4b2276ec861a23edba12541eb39b27891f5d057 Mon Sep 17 00:00:00 2001 From: rebortg Date: Fri, 27 Nov 2020 20:10:44 +0100 Subject: [PATCH 09/28] coverage: add 'set' detection --- docs/_ext/vyos.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/docs/_ext/vyos.py b/docs/_ext/vyos.py index cc408784..4b4b1a89 100644 --- a/docs/_ext/vyos.py +++ b/docs/_ext/vyos.py @@ -297,16 +297,6 @@ class CfgInclude(Directive): return codeblock.run() new_include_lines = [] - var_value0 = self.options.get('var0', '') - var_value1 = self.options.get('var1', '') - var_value2 = self.options.get('var2', '') - var_value3 = self.options.get('var3', '') - var_value4 = self.options.get('var4', '') - var_value5 = self.options.get('var5', '') - var_value6 = self.options.get('var6', '') - var_value7 = self.options.get('var7', '') - var_value8 = self.options.get('var8', '') - var_value9 = self.options.get('var9', '') for line in include_lines: for i in range(10): value = self.options.get(f'var{i}','') @@ -436,7 +426,7 @@ class CfgCmdDirective(CmdDirective): def strip_cmd(cmd): - #cmd = re.sub('set','',cmd) + cmd = re.sub('set','',cmd) cmd = re.sub('\s\|\s','',cmd) cmd = re.sub('<\S*>','',cmd) cmd = re.sub('\[\S\]','',cmd) From aacb7a54ec88ee3f8eea1e669f6f31c795cc96db Mon Sep 17 00:00:00 2001 From: rebortg Date: Fri, 27 Nov 2020 20:12:12 +0100 Subject: [PATCH 10/28] CSS: refresh desgin --- docs/_static/css/custom.css | 74 +++++++++++++++++++++++++++--- docs/_static/images/vyos-logo.png | Bin 118757 -> 68746 bytes 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 7faf7b7f..6d36283d 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -10,8 +10,45 @@ span.cfgcmd { font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace; } -.opcmd-heading, +span.cfgcmd:before { + content: "#"; + margin-right: 0px; +} + +td p a.cmdlink span.cfgcmd:before, +td p a.cmdlink span.opcmd:before { + content: ""; +} + +td p a.cmdlink, +td p a.cmdlink { + margin-left: 0px; +} + +tr td p { + margin-bottom:0px + } + +span.opcmd:before { + content: "$"; + margin-right: 0px; +} + .cfgcmd-heading { + display: inline-block; + margin: 6px 0; + font-size: 90%; + line-height: normal; + background: #f0d481; + color: #2980B9; + border-top: solid 3px #6ab0de; + border-top-width: 3px; + border-top-style: solid; + border-top-color: #FF9302; + padding: 6px; +} + +.opcmd-heading { display: inline-block; margin: 6px 0; font-size: 90%; @@ -34,7 +71,7 @@ span.cfgcmd { .cfgcmd-heading .cmdlink:after, -.opcmd-heading .cmdlink:after { +.opcmd-heading .cmdlink:after{ content: ""; font-family: FontAwesome } @@ -97,21 +134,44 @@ a.cmdlink span:hover{ } .wy-side-nav-search { - background-color : #FF0000 !important; + background-color : #ffffff !important; } .wy-side-nav-search img { - background-color : #FF0000 !important; + background-color : #ffffff !important; } .wy-side-nav-search > div.version { - color : rgba(255, 255, 255, 0.7) !important; + color : #000000 !important; +} + +.wy-side-nav-search>a, +.wy-side-nav-search .wy-dropdown>a { + color:#000000; + font-size:100%; + font-weight:bold; + display:inline-block; + padding:4px 6px; + margin-bottom:.809em } .wy-nav-top { - background-color : #FF0000 !important; + background-color : #ffffff !important; } .wy-nav-top img { - background-color : #FF0000 !important; + background-color : #000000 !important; } + +.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td.coverage-ok, +.rst-content table.docutils td.coverage-ok { + background-color: green; + color: black; +} + + +.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td.coverage-fail, +.rst-content table.docutils td.coverage-fail { + background-color: red; + color: black; +} \ No newline at end of file diff --git a/docs/_static/images/vyos-logo.png b/docs/_static/images/vyos-logo.png index bc1abe15fc425cddd9d0db4022c230c31b4098a6..e3d6f68b18721cd35fba6ea113f6d2a61e0a1359 100644 GIT binary patch literal 68746 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
Z%E5nT;xj_%|gU(LX zABQYz_5nlj;tN08M04>;FS2QdTOcu)zTi6z{yu&-4zR9a-#ZtN)5|*=ef&nd;qGd@ zis5Fo!KDg96XB$cJ1k7cvxlDluZ+mh7Weg~74K%i*!L1dYnSt*O$jq!-Q$l)yCF!ws1Z&mwCyz9u*A_>N#r&t0{jeC>b9!4C*uu z4{mA1{X@M6^?~rzyC1zv!r7;6X&a@cQt>Z^!-g{lO*SAafy%WbOst!t=_1w9MjiNQ!w8q~V14h=sYcvyYwbf{AGD7~ zvC#q&wZnw&5)zMeaerl;S7DW$2;&}CIYq>m!`9%Zowi+j1F{CDF9y;!Dk`f6=xQA{ z2(eb8pF@p8-u_|g-~5g?E?tz}@TP>)FvWl&DPJ=p;3I_@6E`KJVNym*uzup8^a9|h%Q9(g#OOU{7oG>xV8 z4~3G3_Fy9?(bGFr^!dpMk{&?+)XCa+kD^@(BS8~&O_E}i1O_s7P z;texK3m@5nCJM^5mO|Ws@MhbArcsUtS_8TB8%<+9RGjyWU(MOV+cHZ>M^} z5!t@-&W~*4h#gykv7^`m7Cts;h}Lmn5xa|?GwpEQbWPI_b24#nK;~rFs*@uxT-GRP z7$xUToZkbr-)rf*4wZX!awPSu-C3NORqV!6l4#(i{1xxC_)6mWA6y~HcnmdP%?1FY zNi!Gz+Xio;cbYI)lZ+@h;51j!w(C$Mmf(T#mF1u(W<*?V>9|of7 zzGn7BOJ8#_d+@CsP#g9sAR0)ik>s{Lq6dk=IM68M?eC|~<@a?i9#ch@u^w~?RDEpG zt89p#DH!z31eg(F`YlhvMQ>50U_eGva0fjZ5%r9pu^a2*r%HQl24tp!_K6xffDyLo zE1i4w?91Qk$g#)z<~c@1Z~p5&9Pi~vGnX;fmfoH&Rzs|d-w649B09)0r%zvbKOKBS z>mLW#d_AO?X7d(-tg+3+pCnkNW^z85uDKKloYl>fwgG00DjT9_4i3qhIm15T3OOJ_ z7>^>@apD&`p?F)E;%G1SDzVl+j^0l<-v5Et7S!lYQ34b091KTMq8SKGi16TiCGIqA zGay7lAg>lOog!s6kWzbbH;r!pE}iO|Ax>`rZSPr#0|`y@d2DGiq?1v4TZfSMq`mxD*;#FPdKCC89+en-O=WV3>l z0K9BS3@@$S449-)nc8C7>po8x4j!kc_w|7zEv6sROIDsS56T!2s>^8ca8eFrhhZ;RL3q=2zj65F zZHiQFL6CIu%L}%4x|hp4L9dhBGJ2_v9dUu^1PATWg|VKHLKI8U6EI3K=jjcl4>sP| zB_5Dh|v$Wr`&J{t{mTOA06u34Kg5F z14%L--L8(=NcYp%cYcwsXez6J^QJnS-w>VtfhlMQ7CNtEBO3X!poSu=ESL`7BkAf5 zcfDYV?t*R@xQh;2u??c(RCPps+fnNrR}(g)pZRIu@qkF`PHDy8uFkdUvUOL7RX(`) zi*%!ZTSl7oC8=&sa8?@5k1BvM70NTlgIB*vDTez&nD$utna)-bAXp|p_O>`>`HPDK zb$E!flYdY3f+G(KBb+i129jBwef8ktTj}Kb$Eo+u-w929_XGI^MQs8Y+DoUH4bh=a zkK-fW$YTTYjO}zhD`ait!T4NLGU4Xp9UC4atR}suEk)$)rI1$di z=aq37$_V(ZgcwF<G;Dsnj^HEpkP$C!-Mm_2k z>mx_q-qUpD;>+~>_OGQ~bj&G^zCJaeW3(4A%1 zV}OnD`R}w#aG~OKnPz8{p+CZPH=~scL=JiPgJ3ft8cARK#!s{)M(2nTh`v`MFpQ#j z(+TVgm-CU=UEzs<-Mueg5gVbsZ{M=sNYT|o&n_Y(99%9nh@?B+vDOk+cs@JdXHS_6 zI;R_S)!{~uOUl=}qTIvDU}&N7@>@FQ{enI;_3ZO>pxr86^-yg=5-VcHmYyJ7)t~W7 ztAd2Qqa>seAaAj=lP^WSXtJbT;%akX@Z@;POj57vTyw8bH;^ zAb<;J0q%WWe&Oj7ZrPDX6kTrh5w?*#B5?K!v*OGOk+IM`@p3EH@WyTO3SQNfK{PP2%L2O%IKbamG0gCuj%?lZQYe2=4*pyY#F`D=-P{fc?9Cz z^Kh8w^|l=CVSfxZKjv|Qx-uS&C+*KV72dHi!>00&^={M4{>}8}H~*D(9AiAR_5sdh zHxO_`Th}olQBZ+yv=^tU2!6#quHzP`dD;AR?Cp0=^VCJ1M_3_sDlAKmNf3__7s7&k z(!A(Thq3}k#WQTSeB^NfCT2HW2t*0@2oeD?twZC4M5B&l9(r1Ey!mnJUHzs`N&i|3 zMvJNH-D_^c67g;6E*e|id3x@yfdGsO!u--$gKrCRN(kBDz<5ucWW=ot8fEIv)=?5_ z6w=r2NZ(BF4DY3vPyU?JV_i3IXBOODwU4LPxt?rp56alx;p$yYF3*Iure4A7TlG|c}X7X zC79&}+OJt9e^!D895Uo^F$`W|en$kXRE9w|ic&ObH5wfX#}iG%9$f!cN;kfvnX5Mx zsi`{ZTuBhifNDShR5%{uBGv2ReAKWwy`F#dyy|zXm$-Vsvq20&AhnB(Yb2f{E*bzS zNJHa5(!56#AIfpoW(id6F1S{4fP9=1L6zy~A_KiLEjS*$ldiq{lXOqpVy}0!!zo^0 zSEJ?obbJPsNdcdaMm>vXHg^tBY4Uy*U==#I3p~kK03uLjR^aZU1@P^J!o@ts&O+KJV#iL zTIhzMqh7$0k|blmmyAV`_NiLd=rAN&+$SkVKRz2>O>chVr?MOGC`{k|V5$}{2s=(- zjP^6A2HwP43QPXV{#boM-D0$^%Wwq0_5H|y4FCDx3kjiUJyf(L3Mix}ga+wC3Fdpc zlsbC(Xrwz$h2~Z7C@5g$6pPhIJ@}hqx97u z{-cb=Jw-lJZ;n0kN-5>-{a78cXN{Y_EfBc)g#k5uvDjIEGCXcJRpKDM1OuUApK<8sUzWb|m?fAb_$XlvfWw3hDovKtlLpxx|$0U!-2%;`uIfKnIFo4ywu1JMv1fVnO$$ZH$-Q_;35(F zlOLI|Zi9^qQTk17W;!o@XCLK&qhPVtVfBLF(Pp%PEHdWBh7dl`CkakvI4!=BL2)6`Yk0x5y z+mu34BjKCi9rbFScRx(u{@4F&>R$RjDGh+72Tp)7cnT=sX7F2a3u=wXDn6XT>6A!*?Anc3-APkA9!hS6WPe`(xqC(yN@&t{q0U z6UlcWS&(%w#&~XPt&TBl_aWDeET|zk=XE2pjgJ;0zIm@b#){6G$7%HCFVkc3?Sq3C zT2rEPKqgFcK10eH6D9{EOiAPvlx#%wkP9&1fn4^`|)esItv{aXHr&rlsM!d?>+0mg1iA>H0)a#ybvdaG@{3v_{tr3(sHkJh*?uy zUHbD38`E5r3c9#_ckF3?Tu=fn^y)MU8Qn-X^bLi(fBpB;w@2x)r@o%OG}xD70yfhf z)!pBFKibdM+M3Y=?hCy?fm_JJAbj`uYhzP-m)twy0^r{IPbh-8g!d z`h&c6*Z7Jl;)35UE7SphQ8$bftUO~M^|81c*E7JtHOm-at^R!zh<5}A8hPko|Itx; zqD>(0y!#_1@>6#mQ{V96*nq#ARiVCj^KhVKJm$%^XxjdPefIKf_VY3z6$_b#-5L%8 z$t8x^4p6hS7!WB=-bz(?&t5`9{BqjjzC%(6>bSTY>Uyxb3O&#e;ChwH^-cr^jFZCS8B@7cHp1BVBV%@$^O6#bYW;zsg#{v+__X zbho_F6*LwEQZKr!*5zU3$>oMr3R-7~r3Zg9qkH*8-~CXWcj3w5Q+~xdhq1}HXS{bK zPu&Oqa@-PZbZFMeu)J_=z4fX!VK(rj|ZS~_reQEI0H&R#cG3oqvr5DbY z9pmHE&>3QeS;95Ey4Q8Q1>p5{MV+263p8V%dkvH2np8{%);uqbxC$!Da#8Y9vSASX zZk84X{Qf~4Qm|`<^ySNQdRPH80(awXXnSLF#?TOjx<+3_`6LekZb}kIdhjyVdw-Lj zes)`(z~j_E)f?YRY)#V)5WP8IIs|#-*vkf-B^}B_|EM|xue(i;0h*~Ri&rcLCfAqU zl$Znk4u{XvmBXj$Sl{tJy!Ab0(pg9vbvSl;Rm)&0D$q9o@vtQR8_f<4@D9@4Zx8nD zF|d!CW@%juA6nyjBwqbfx}qaXjyOw<_D3DF&R`%&r$=j-#3@kihwcaEgc0!(LM}7k zEPBo#;Cj~vAQ-VMXVkr(!GqmpBh45L^v=@B!J8(l>EgS>O`j+*+%S+CZ-YTzcRqCs z<_Z&yE<1W8XbHR>`YZ5j^}IPcm#VM?}lTfu=WSyXh*Ws9B?!nS)|zInn>CZtNHQ9jB)QojZQRyg#fct}I>BXZz>b-{FngQ`# zdO0$$f0TL(k_xy30Y-#@-}N7ABDU@pm2K7Ib;k>J7Je+_diR&<#X}uLIe03z(ng#Y zwotA$2>3keYNTRoC&YW!GQSuzn4&kCScZ>+Wa}Q(3PunE!bJ@Nm%`}?2`@T+y({U$ z&5!in&$neKu2_0fk<&W^%1hHHTj7u_jEJ{}!T=J#;of(F;ud;nhv%^jp$@HTYvLNI zCu5hwS*UKjc<*4TOVYx}Z@9GhYj-=ML4JlC5eGgBA1MuIcY&L~X}yItH#bVOmT`-5 zAHOt8{<0H0?12pgYWQY66fm$+gcQv1N_ywRpQhte-riNSoGr0MSx{2kM(%yYwPG{QTz%@NLJg zG=W2+7>$j2V!;J-NVA*H`bRAC|sBAhET+28hQkT>Vr|h!RPPj_W40YNtyR+0u=&=5A z+Lw&}SbZA|qNXV=k^Sgd@`8Lif_8T=ZNTf@BayFgkvN|B_wzCw!D+p`s>+$TDz#Xy z(Mi9gpUQ0=p`cV6FO-|2?T6;0ixx$CE6Z;dPg#tE5mx;6i~xlz`y;IGK5M$VylV^# zU1>$ogQIbC&u-jm#2Oy_a^9)Yc5kJ=wnlbzz~Z2v0T7EhtcG9bLaFs@t=KFChsp>74D>~>zGYxWi_&~VcOZPtguj$rL{zmCv>X~;M z=#4`K;}leBUJ*bL2ws2$<=PGh{#cyC6dv%a+fy%TeMTLzz!cCukyl$?`pZ9Oc@4EZc?E6X?+I4BX9kqCfs&oMp{^|nyp zS){>JJOFIB992WzctbDVW-nVmWC*+v50I<=b+aATSe5He>E)7t>Q9H1B<%)I8R3l=tpmU zS4#M1I_NXUEG?_XOUh{SvD?LYI)+h&JHR-x7VC4ZuHR64w3}#7 zNxItOFiL%l37#Iv+?)(Ny|`5v=HNyEw&yS`Ig(Lb4$mIDO;b1(<6$*QA;6-2GCQEQ zsfsOdQ77RctyV_)j0b%!*RjZXLpWiF^MyOf1oNn?qkzq1=2cC_BkmI<| zf;VYbMgBbHPTU~`IYQXebuYHuR-uP}B9^BBW7HX&{7X9*G2%`kg z5z=R>YId?}dPK8lu1m>iBAW)@Jk}TXp56U}4w?OD&6DeJNK^0F z*K&k^zw^zqOGdw(VrEE5dnbr&0R%-zHkl$;t5(y z+3rXxMbl8Cb4;a1Ak-T)j&xLyruAOl{dKx||Gw%}FN!LeiDhkJuU}wcq^FQRYq}|5 zRvNuq1|%!7ZDiz1Yh?~#q1SyOPKu|iqarSUGhKP>M`>{Ih71VHTvAfGt(QFRomLhF zL?JotYK%t)M$c7?#cb5h1HV8gx7p#nh(~$AN=uAirp1C7de7sQj`V zD4CpoG4A%DMShJwP9=j^^~r&BB;&z1Y_wK~gHF$5kFV`dnTKbXfThi@HC-gyz=C>yQKunB-~ z?RE6tN^kfqUDNc{{m=N!z=MYpni)w7JJKa2A_7A+oCVaD+Sdc8S@Pql0~`$ zdOq#w;Kb7#>H7PBFPW5Fny|)c3YbU?=iZe$Q1Cti%k}a9v-e(Ik{n5*o@ZvM?y71n zfCd`CUjO;JzII;k+Sh z{1QugIpX~Slj&O=m)&<|Oc=ve#+Gliej9GZ@5J69+eM(zlIF#mAsL?T_G2c~f6Hx! ze+0*Tny@;sX4a5d=Gx4@EGFkA@=0E!m*LV_4o=*9_(xV=u?w9ZTF1?_4EZ@d(xAxE z69F6!L|v4a;XK!@Rv_?|J>M-Z30t}JeoD9LfiRTSEWliPDv;CUzoRGHED%SO_ACHS zF-~14PZWpJiWyT56LDyCF>~?WVGbwjITvYfr>iS3(zn0+Pw2-7 z;EA6?6O_f6;8@*F?K8#$=dzfcGe9ShIdkKFrzqFK-wO#jmFSIiknOE0BXIjdMi6(?!*ZOD9rQBorle+xqEOTDp-sYwxh+{&w2x zuF)dQ{?QDyCfn3?6PmU8)QrN2byXn|#lxXE+<5o4zDxb5pRj@MEA$)!)O^A_Ie%hJ z9^x_lc{Yu3`me@*xpmjppgX_}Tn`!m>`>BsI+3dKoCu9@#-E)f&*0DRis?FmhIAnQ^M?cKB z_hp-p9adr~g*r6B7f>3VXJ4cjU;i52@h!fb?FG(Wi<&Vu*E!x{(mGpV&2?6U=E=Ne zr9hu?^V{^`b5^6NK%hn3DbDExgHRguLhJC z?i-+1S}}R-k!;%v^kBQ*<#d@9Fi+VVvc(3jen=>WK3r-^;HmZZ5Q=`jOn?C`>MTOd zhr=>FoVT&aT*xwarpIJ@m;2s5%G_2sQF2zR49C}eSe$O`VQvDCQ0fdRO_`VP{EYJC z&U4C$gZ%kpQ9yK6a0;}KU;G>{KW*s4Qs7LLVB71MrTFs3EgPoRN!#RIdl=EeB6zcV~|$3 zGkx>BU#0XNy^tM-ba3w?fRwTBz>c2ROzEDLNY4F`wNTi3Mkn@uY_tF6yWcT-_sevV zWzAd!3&QN#NAVk~qw=VSAdes~(sMsBgvmm`5s*l6QJDCnG`6?Ek<$;Jaa76jmG_uD z=i1s(dazua)8))ZNz4=#Kl`TKNbu#fjtpO&vn-yP0vT5pZLeb%&anog5ELv5UD|mn zkOls_4lCFTS$Hj7x#cOnm+@6#QRD-Muu284(hVUt3l8(dQ7YN1@bMV>CBFC@Fx0`W zbgx^!L`!^=mbk}x#J&i^X0c=b=1Kdk#5EsYpQXlEQ83rTwY4uk`{#6h@o`#l6&h|1 zU3r~z2wckw`W(p|R*~mGp2dh#^nl~|m1PF07TGJvrBOFoeZ?M-nA0MQ-gTeLR~2Hx z8S!N)!&xYo<202=(>^=IlZ`1yo~RjD990wSL~(d&60;sEcc_{kWx}n~l^r!g-Hg2< zTdV2fYd=C~Twrq3o{2?nPsBSscnRZFln3dCAgKi5HaIa)W8<1p^uVc0?_`BL(;t2L z8|DJO!%cUU4N+Z@r2U*5ch#%(Lvg4)R18nHdgu+oV^fwk^|1ZTD$W@+*UG5o}pPsrATPdL%zQ)DbkB#w8-BU-OHg~=F3^r=6_nI+y-fU|fM z1fn-+UT6Spf0G8!{*?L;K29qhZ?k_4lV`4gr~h1$i1hambGTIct( zB2}NEgB`}69c2z7>yTFL6+mIIBmMf@|7&{EzssHw1T%9BoKggp+2u`7#K~)iAuNIz z(+*XHIzl+OaMop`SVFEu`9wgzP09!Bq$h}KylDnr7|^QT;aKw2b)UmCjwiR59E{@kD(d7rj<D1bP8d~5?vcQ;dlf>JHwlud-1}%IUi^KRr|CbzJ|}S| zKsWF#swxLVDmqoeJ67_vz)F~_AEt%1chfev6%HJ7sAA;M{$?8%iJu?B)F!Nr zFtrDkjKbu1Gu)WnXnmDPfJIo*Le1swjDTGvJ;k>14X?Sd0K)K%l?g z6-o_E!)y3ckQ;Rwew_guC`RAWygm9TZ9MoLoe_?4u_vj3mlh$^L)-A3GoI%j4vGJC zLS;aqEHcdsx$(7N;h*tRVO5fyA;m>Xy0?7%fFr2%g)y)we(K`x71}e;b zEH7+uXF7tF^Rl{JdCO%OfmUQMk}r5R-+GkqVvoS_)ASj-o}f(xtbx3{gXgr+H`Dzu zexEKZF&spzJtl+#9eV<_@`E-;@S)6N;lz*v2Hi7H&7cbPNj-pQabzgN#z<{535a(cYAkZ#@m03_Ih6gZZ!;ww+OP@>|~IvvBb=G;-B;vY-)#Er_MHAhQ< zJTPE8Rzd7!Yc5(vL9}4|%jv?M57MK}<@AD^3wKa59adx2!XRsl_{_ya%&L-)3@HXY z%dh!_;|xCt6M9O~=q)`Ck1Yv7X=@uH#f2eVmBrSB^ngp1Vt2MjoFlSa4^XfuiTgb? zIrsT{XxBFU8iqa7=X@?C^%AW7LoZ$kw_Nk`*ArJ|C}X3zXo zdCxtD@=;<|WnTysRIyY_$y9IoBzVR6)f04uhdL{1Yw>DYyUoxQrys~`gPP`ICNE|q zpZc`s98#d>fg$d4$BCG>*Ktf_4gsSqs)hzkCfxXm2~WO50XUhyny$X}^K}0OyV7Yf z=2oE*D&sT%O!QjaI6yV_M=4)hsZYJP zw4{J_A%FsP)Qo?R`0nXB5^{!**?{lF3B)YbUD@C+`~Q)yEN`YIZeoo5$FU`#0+9-J zoG(&!WTUd*C*9&bF`S-0Dv=Vfq(r&L1bf3P!jw3;iw8Z64SKiVJzq{Y-u+8Jacnyi z|1LR}{UQvOA@l~H>fM_2L4k?V!u&Lp0iXuHpLa8L$CmuV`M&Uf)-qB&L#!+;h!RNW=Fp8 z-YoCgQ*C25DPTS3FKwj6e@-$eSAl$;*>Z{voZCx8(uLU0K>yr&b``R$8#l0 zBt{$@5{-NeW6Gy>VhwA7+P=>h1?E#A@|CsQXNqa=`Iuy%5^XN$S8BMdkiKe-y0O5P zc|ALzY^W;nw#uS&HLbt%SKL;($_c$*HpS5s3UbHQ%M;%M_9?<+SR{I9Q^J(*!@h}M z9mQfVBcAwn#ZFE{A*%4~GIpbATI6uSC$!cRC-p9J>w71T|4;-nU*gOywq1=Tv#`sU zc1~lL*NHfY6f4dWheSUAlGRuL%+S^Sbdh3U*+7t@!vcbAc)POBqiLc%q?L-+9^`~P zOw4ZuYSIgZl%q%!)2!YBTOS^me%E!~G`Y0}h4z%Ww4DpL(#oBmvhCw_a+D8c$;sq6 z8Mq*RaGu#t|Imk$bL<9^!t<|9@vf5p%hd2`VKUZag5V7u%( zdLTKknQoTnSh|g3!t(%TQiKAt@{99jEE|+GNA3?O3(w{9%Gy55!!O?aJ~t`fA+1Zn zV{%#?_!y}ROBc(@GA?{-{^i|C=|{x&=NwSL(wuA#D&R})C{PX>uY_;kb5Ov_XGK)v z@Crekzpb)$)pV(BR91&Yoa9_jm)`twdf2}}wPu&IM{%P>6bi1938ADg57+@%;5_+N ziD^EHpb4MZegbEsDolJ#U%{9KjS3|8r9|(E+Y0+nX{A3&4?p9s3{I*|>q`gH={cl)vEG z+TP{2IJTY5gDm5fw^SeUS}2KKGN5v=Q;Wi_zgo)~p}?+k8^x>HJ04XaM%*XzD5%EQ zq> zNiU@Drb1fnp41z{7kJggyHSkMe41pz>)4Gr__(uN5ghwIsy!X{p0>aIb=rCIXXbM% zMOfv(!<<92qGlp^`4+vcs8>aW&v1}ISY zW(q2~F%+Cohp<$$38pL`?fZOCz)DCF))il@t)ydP3hKpXX0GgypI&Crv|UD?k(^@$k|F51ID7LO|uAc4#Unhq0<900^rXwh2LGqWZBX zgwlWe9T|;9D-D3c+JUVFhTi!_t|gK+QKuG z0ty6Ldv9MZD2u@AX+*-Rba+CZ2e#%!xQJ#R-#(F0^BrNQ{Ro?QkwzfcDCP{ml#MLZ zhcEI*M)<_V7d?3B4$F7pr5z{uA%8AT0*~;du$jYYDvwaPs*hl`4HfDxc z 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 literal 118757 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∾k7c9xg05HH$@p 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%0AU4}&8cG4fDK%riN4IcBl0B!9_P^U1ucMa zO?L1m3bN`@azRAE?CJ69(*W5!j0Me_5SpYhQ=c=|-gmFXC_TuaXk>Wn%wM{!xn&Fu zVhc3i(6o`+joN7?hKR=)Xsb+G%>;SI%mr(-NM^Y?|99&p)@!qZS<}40&?gkSu7iSS zmfyI|%iF8$@~yk%dmSHk=alHj#}C<+_|A9z+t8Vp$2!YLVo}mk3whx$(tD@rFO`Gg z+Z=Ft4#oXU5=m8*VvtSK12U(py?3#uW`wP1!Z$#)u zt7F0sC8r!j6dRhT5YiZ!vz28yy>ezxOR}Izy*osqjGJlmU0)(dQpYIHT4(>VcM)9U zKJ&TrL7c^E61b;b{1SlhJjQf?0HmLL0R%r8J2Z99{$E>{msKd)XRpA`q<1iO!}!}Z zbHoWmd@X$H<(-sagHa8`fFy(SXapnyB`e*s+G}XH62^|$3igjd2^%P4x(|gNE#RNQ z3J#k(RFw**PZ3j`=^NDtwHyQV`g?@mSSSa>3YjC4vf-AyuMbZ&IjB?`WLh^9_m?+R z_xr42QDxic`*XG?y=D-aXdfF^HXheDR#Cj62jxABPU~{|SRyR;k1t^}O@?FYgfz#k z9A#=(69g2jYAhj$@DIL>+ENX{zQgr_6}^2+k+&DWQ22y^^%_0=KzNj>x_T;7 zAAFwGU-^H>=DOG0k9q%mfne1)o^jft^;KT0RKWH z#V?j|@>QyVav#MTR>(4)DREi=^!{^6$h42Wdg_0pQw{?f6N%8CWh+5@Gx)3+d!0{U zY`0zMFmXLzYXo47TnS*DV+sMW=;|yiMe_2%u6bWuCKx@R4h~%07|WRaVjtWqggBEi z7SZap8XS(&2ByIv>0M>TR;DCSxkeY+^2y&k;2Ibk{#E&PF2lKb1t+p5`Aq`gIXEy` zxcnAM=6R-`wuSG@OC_XpjVL0fII}tpZyJnBhNH%plU3Ry-Jkh1s1cE5zESkpdum!G^#3QAK)V)h{+*%L`|=6NYIJ_#)Sf3;G8w^ zPrWX0i)x75#xp!5Z6fIR7!4BFdZK~3FMK(es1@T=pH|#e;CLvJ($I!63$IW@82&kS znOk`RY;iMwdQd8=-==%1ef5L3pL!L};3CDRt@eKdmMs#zFvhM)I)AiG89KgsZE9T7 zSeU1F(=uFssba5AcbgOa`qpK=J(!^*!s)ReG(EZp9Miautua?171E@C_5o*28z|cF z@Tt4;N+&X+UIBZPOY||KH}3gPyB)Kyr?w{zTz+Ec`02}WV8Z$uiNj1BtKTCVX|Fw& zm-q3J8Uie9`fyke^KQyC2AT$gW5Z`&dVy`15O*&BId^B?irGG!K$x7AsVv+TTsB?s zLc|mMQbmLztOSe3lP(ZywT2%2?q`Wmd8f?`9z>yyw2Zmh48&73x}l%w^pM0DJHS?Y z0+^)6JDO5gp9O&n@Tc6Su-yRdHD++nQ^e)?TiGG}<&W%n_Qn{Eh3UTo^};}$z1$

UCJgZyWD0l*4R6mNsS5ifV~;EMxyGpengUpCEew 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 Date: Sun, 29 Nov 2020 19:05:51 +0100 Subject: [PATCH 11/28] Templates: move draw.io template to _inlcude folder --- docs/.gitignore | 1 - docs/_include/draw.io/pbr_example_1.drawio | 1 + docs/_include/draw.io/vpn_s2s_ikev2.drawio | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 docs/.gitignore create mode 100644 docs/_include/draw.io/pbr_example_1.drawio create mode 100644 docs/_include/draw.io/vpn_s2s_ikev2.drawio diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 69fa449d..00000000 --- a/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -_build/ diff --git a/docs/_include/draw.io/pbr_example_1.drawio b/docs/_include/draw.io/pbr_example_1.drawio new file mode 100644 index 00000000..0d496572 --- /dev/null +++ b/docs/_include/draw.io/pbr_example_1.drawio @@ -0,0 +1 @@ +7VrbcqM4EP0aP4ZCgLk8xkk8u1UzW97K7FyepmRQsGoEYoUc2/P1K4G4CLBNJo7j2rLzAGpJrVafPq2WnYl9l2w/MJitPtEIkYllRtuJfT+xLMtzTPGQkl0pCQKnFMQMR6UINIJH/AspoZoXr3GEcm0gp5RwnOnCkKYpCrkmg4zRjT7siRJ91QzGqCd4DCHpS7/iiK+UFJhm0/EHwvFKLe1PVccShj9jRtepWm9i2U/Fp+xOYKVLjc9XMKKblsh+mNh3jFJeviXbO0Skbyu3lfPme3pruxlK+ZgJn4MU/ArY39bX3eKfT37yffHh8w2wSzXPkKxRtQ+XCIWzCD9Lq/lOecr9dy1NnXG05TeQ4Did2LdiBEFPXDxET+H+lN/kBciyD9jZtpkp3mL1LFbIM5h2ZcuuQGoctGPUUn8+LkClSbimVKYvIMS9RYVsyDghLryiS9/HUa/zCwgswzSAMcI5YxxhaZZYK54Q8QZE3zNiHAu2fYRLRBY0xxxT4Y/7JeWcJmKActB9KMIYMSEgcuSsJtcdJZQVait6NUpv1VxOM+klzujPmsRWLWlpME3fnEsEnjAhQ5prkspBEcxXKFIN0ZPJ7SXbWCZCA9PcM7DISrkRErqOaj9I49B2L0lBTX2RUhFNEGc7MURNuAkCv5yj0qkTlM1NKzf5SrZqpSVgqbQLVT6Ma91NThAvKi28JEU4r04RrLDzgnOEdZwG58kRJ/bUKZKEZYzwzjVJnDNJeO6lJQnLHUgSHcBRJAov1cxRnIjdPjSiGUqjW1nPSZgJzHMcCmErSNAW82+t9+/S58ZUte63CoKisVMNGa0tBGf2fO66fWSjKfIjZygWXHdmzee9uLFrIOWmDsMofEDXLEQHvBcMw92Csyo622hWMoYI5PhZN2MIYbXCguIiK1TR5HeiyfV94VZNS7kDNbFdY/Z0TXVdoK+LQxYj3tMlsIe71rBMDsgPmd1Zyp0GaqnR1gnz9CnipbSjYUKNxyvIEZyNHOb/jxzWu5LD87wqgOs48w3fbj6/SxXPORtVukv1qPI2cQ+s43HfPTFDnIfUEIe6OOdz9dRDXTtwO7Fq2q4feEOx2hzevQLgaPUxXEkUhUf75G9qgpAmkqA1y+YwwUT6/gtiEUyhEqsvQ4B1qruDr0eq5Vcwt9li+85AZVCVCyevDGxwPAhkEZft9YD65gcuq+Hmiz3jAZ0AU98Z8AzwBxIJqDLJ6WumnmO+fLz9C9RX8iUbLvH3lfMbZbUs6FPKEkiGS3rg+obA2xD7msuCcE8R38Fos8IcPWawyNUbwVWdlSPZoLMPjOOHM1CLT+Vfj+gpTVE1WZkO9hJ4FOUOxPTBM+nMsTR0Rx+VaQU4WZFrf8A0+pEhhrMVYpDkRtYpMS4j754cM6XGcbUEMXCj8vw+oN5b4TniOnXF8xCeUx3P6TvjaY8ohd78FARmtb9LOgb7l6PiGDTPcwz612Pw9yl4/Gp25liqflS85s0Xg3aZ5yAYcXu4AnoRB6FoNj9ml18hNP8xYD/8Bw== \ No newline at end of file diff --git a/docs/_include/draw.io/vpn_s2s_ikev2.drawio b/docs/_include/draw.io/vpn_s2s_ikev2.drawio new file mode 100644 index 00000000..b240c191 --- /dev/null +++ b/docs/_include/draw.io/vpn_s2s_ikev2.drawio @@ -0,0 +1 @@ +7Zrdk6I4EMD/Gh+lSMLn4zgz7j7cVk3V1H3svWxFiJhaIB7EUfevv4QEIYCje6eOW4XzIOmQTtL5ddP0OEGP2e5TgderLywm6QTa8W6CniYQIoCA+JKSvZJA2/WVJClorGSgEbzSH0QLbS3d0JiUxo2csZTTtSmMWJ6TiBsyXBRsa962ZKk56xonpCd4jXDal/5JY77SUmDbTcdnQpOVnjpwdccCR9+Tgm1yPd8EomX1Ud0ZrnXp+8sVjtm2JULPE/RYMMbVVbZ7JKk0bm02NW5+pPew7oLk/JwBv/tf4d9PP749rV+/8DAihK2iqRwg1bzhdEPqfVSr5fvaQtUeidQCJmi2XVFOXtc4kr1bAYWQrXiW6m6tjhSc7I4uFBy2L7giLCO82Itb9ICp43pqjGZqilytZNuckOM4SrZqHQ6qccSaiuSgvbGMuNDG+RlDgTs0FLADdHeWOsNQwhXW8jLbJTKqWBEtI2YJ83FSlPrbtFaMy1VlWVs0ljRNH1nKikobspEXhL6Ql7xg30mrR/tj3VP7tzDpTBqeiijwG16Q9IWVlFOWi74F45xlrRseUprIDs7kATZHLBdycGnZiFhGo3qFLOdznNFUnssfpIhxjrVYR0AAL8aA65gMwNDtMYCCAQZAEF7LW0YGbsmAg+4PATQicEsEfMe3XBOCAKCPhsA5DQGJRTqmmyVJMrHh50Y0I3n8ILM80ZuznJg4kB3lf0lbi62r1ldteXn9tGs39q0zabExQ/O55/Vpil0SxM4QTZ43g/N5jyakJ3ohBRXGk+SqyXNhSLXI6rCrdrVMK6ybzUqr1r7d6uuL51SeQtVS5pQ2fB8cYXK2KSJy+rnNcZEQfsqx+yC2IKsz5DZjtawgKeb0zVzuEHd6hhdGxUYazgMPWQFqPp30B3qmRrVrraSdHPf0hu/p9UPf8lof15xF2aw3iwAX71u3reUN5bubOxLHjy+7O8LxT4zwbfDuCHGh1t14/eGU/3sgcMdA0AoEQXDPgQD+EoHA8aDhsHbHZcWbutVx07ODAfKBBfruXqt2PTAQKy4dDKADf9K1nbqmclPXBkOZnpeK454txEXCKzqVQPqc4fXePxtWd0zLKid6EDeAYL1rOmstwIcWCCzRbYmNzqFTqxUNpdmcTYhbK+iEG5FrcTOImA6ug0w7GmgR1qlgJDyrSlC7OWJG47iKWUMlADN1vETq13sGuHY/+weO2/fFujR1+RrAUOJ3FSYs6I4YqAd7FwOvrvu0a0H+LSkYeupfhwIZ+UYI4DSEdvc1EDWiDwPBG8PBrUlw7LsLB/4YDm4MAewWBg9l/w+DILh5tgjHbLH9bhPeXbYYHkXi/xHwxmkTCBZF98DLNc6PK9/qnUv1OSsynA4gZlvyT25f+tWBI6W5h5dJXYewE/8uPLPibJYiwOSsGrQz6VU9lq78O4q5HKyXDgaQVkXyS9AK7O7LdwgGshlYv/0blQZ0JV5rR/hlgUUjsNcCtle1Ce2PpvUK7+LQGcK3qHYzPmWrUlwv8Rp8CxsokF7tMQuv8Do+DEJKliMH+vnldP9FNZSBXwYD0Wx+TqbKu82P9tDzvw== \ No newline at end of file From 371bf8185f3cd0628969a8603aa92503b2fc3853 Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 19:08:35 +0100 Subject: [PATCH 12/28] rearange changelog, cli, contributing --- .gitignore | 3 + docs/automation/index.rst | 9 ++ docs/changelog/1.2.1.rst | 52 ++++++++ docs/changelog/1.2.2.rst | 46 +++++++ docs/changelog/1.2.3.rst | 62 ++++++++++ docs/changelog/1.2.4.rst | 65 ++++++++++ docs/changelog/1.2.5.rst | 60 +++++++++ docs/changelog/index.rst | 14 +++ docs/cli.rst | 10 +- docs/contributing/documentation.rst | 89 ++++++++++++-- docs/contributing/index.rst | 13 ++ docs/copyright.rst | 19 +++ docs/draw.io/pbr_example_1.drawio | 1 - docs/draw.io/vpn_s2s_ikev2.drawio | 1 - docs/index.rst | 114 +++++------------- docs/installation/index.rst | 18 +++ docs/{ => installation}/install.rst | 0 docs/{ => introducing}/about.rst | 4 +- docs/{ => introducing}/history.rst | 0 docs/introducing/releases.rst | 29 +++++ .../index.rst} | 0 21 files changed, 504 insertions(+), 105 deletions(-) create mode 100644 docs/automation/index.rst create mode 100644 docs/changelog/1.2.1.rst create mode 100644 docs/changelog/1.2.2.rst create mode 100644 docs/changelog/1.2.3.rst create mode 100644 docs/changelog/1.2.4.rst create mode 100644 docs/changelog/1.2.5.rst create mode 100644 docs/changelog/index.rst create mode 100644 docs/contributing/index.rst create mode 100644 docs/copyright.rst delete mode 100644 docs/draw.io/pbr_example_1.drawio delete mode 100644 docs/draw.io/vpn_s2s_ikev2.drawio create mode 100644 docs/installation/index.rst rename docs/{ => installation}/install.rst (100%) rename docs/{ => introducing}/about.rst (86%) rename docs/{ => introducing}/history.rst (100%) create mode 100644 docs/introducing/releases.rst rename docs/{troubleshooting.rst => troubleshooting/index.rst} (100%) diff --git a/.gitignore b/.gitignore index 06d7c4cd..27188bd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Sphinx +_build/ + # python virtualenv venv/ ENV/ diff --git a/docs/automation/index.rst b/docs/automation/index.rst new file mode 100644 index 00000000..a3df9bc0 --- /dev/null +++ b/docs/automation/index.rst @@ -0,0 +1,9 @@ +############### +VyOS Automation +############### + + + * Ansible + * Saltstack + * HTTP-API + * startup scripts \ No newline at end of file diff --git a/docs/changelog/1.2.1.rst b/docs/changelog/1.2.1.rst new file mode 100644 index 00000000..4f22dd0a --- /dev/null +++ b/docs/changelog/1.2.1.rst @@ -0,0 +1,52 @@ +1.2.1 +===== + +VyOS 1.2.1 is a maintenance release made in April 2019. + +Resolved issues +--------------- + +* Package updates: kernel 4.19.32, open-vm-tools 10.3, latest Intel NIC drivers +* :vytask:`T1326` The kernel now includes drivers for various USB serial + adapters, which allows people to add a serial console to a machine without + onboard RS232, or connect to something else from the router +* The collection of network card firmware is now much more extensive +* :vytask:`T1271` VRRP now correctly uses a virtual rather than physical MAC + addresses in the RFC-compliant mode +* :vytask:`T1330` DHCP WPAD URL option works correctly again +* :vytask:`T1312` Many to many NAT rules now can use source/destination and + translation networks of non-matching size. If 1:1 network bits translation is + desired, it's now users responsibility to check if prefix length matches. +* :vytask:`T1290` IPv6 network prefix translation is fixed +* :vytask:`T1308` Non-alphanumeric characters such as ``>`` can now be safely + used in PPPoE passwords +* :vytask:`T1305` ``show | commands`` no longer fails when a config section ends + with a leaf node such as ``timezone`` in ``show system | commands`` +* :vytask:`T1235` ``show | commands`` correctly works in config mode now +* :vytask:`T1298` VTI is now compatible with the DHCP-interface IPsec option +* :vytask:`T1277` ``show dhcp server statistics`` command was broken in latest + Crux +* :vytask:`T1261` An issue with TFTP server refusing to listen on addresses + other than loopback was fixed +* :vytask:`T1224` Template issue that might cause UDP broadcast relay fail to + start is fixed +* :vytask:`T1067` VXLAN value validation is improved +* :vytask:`T1211` Blank hostnames in DHCP updates no longer can crash DNS + forwarding +* :vytask:`T1322` Correct configuration is now generated for DHCPv6 relays with + more than one upstream interface +* :vytask:`T1234` ``relay-agents-packets`` option works correctly now +* :vytask:`T1231` Dynamic DNS data is now cleaned on configuration change +* :vytask:`T1282` Remote Syslog can now use a fully qualified domain name +* :vytask:`T1279` ACPI power off works again +* :vytask:`T1247` Negation in WAN load balancing rules works again +* :vytask:`T1218` FRR staticd now starts on boot correctly +* :vytask:`T1296` The installer now correctly detects SD card devices +* :vytask:`T1225` Wireguard peers can be disabled now +* :vytask:`T1217` The issue with Wireguard interfaces impossible to delete + is fixed +* :vytask:`T1160` Unintended IPv6 access is fixed in SNMP configuration +* :vytask:`T1060` It's now possible to exclude hosts from the transparent + web proxy +* :vytask:`T484` An issue with rules impossible to delete from the zone-based + firewall is fixed \ No newline at end of file diff --git a/docs/changelog/1.2.2.rst b/docs/changelog/1.2.2.rst new file mode 100644 index 00000000..17ba941f --- /dev/null +++ b/docs/changelog/1.2.2.rst @@ -0,0 +1,46 @@ +1.2.2 +===== + +1.2.2 is a maintenance release made in July 2019. + +New features +------------ + +* Options for per-interface MSS clamping. +* BGP extended next-hop capability +* Relaxed BGP multipath option +* Internal and external options for "remote-as" (accept any AS as long as it's + the same to this router or different, respectively) +* "Unnumbered" (interface-based) BGP peers +* BGP no-prepend option +* Additive BGP community option +* OSPFv3 network type option +* Custom arguments for VRRP scripts +* A script for querying values from config files + +Resolved issues +--------------- + +* Linux kernel 4.19.54, including a fix for the TCP SACK vulnerability +* :vytask:`T1371` VRRP health-check scripts now can use arguments +* :vytask:`T1497` DNS server addresses coming from a DHCP server are now + correctly propagated to resolv.conf +* :vytask:`T1469` Domain-specific name servers in DNS forwarding are now used + for recursive queries +* :vytask:`T1433` ``run show dhcpv6 server leases`` now display leases correctly +* :vytask:`T1461` Deleting ``firewall options`` node no longer causes errors +* :vytask:`T1458` Correct hostname is sent to remote syslog again +* :vytask:`T1438` Board serial number from DMI is correctly displayed in + ``show version`` +* :vytask:`T1358`, :vytask:`T1355`, :vytask:`T1294` Multiple corrections in + remote syslog config +* :vytask:`T1255` Fixed missing newline in ``/etc/hosts`` +* :vytask:`T1174` ``system domain-name`` is correctly included in + ``/etc/resolv.conf`` +* :vytask:`T1465` Fixed priority inversion in ``interfaces vti vtiX ip`` + settings +* :vytask:`T1446` Fixed errors when installing with RAID1 on UEFI machines +* :vytask:`T1387` Fixed an error on disabling an interfaces that has no address +* :vytask:`T1367` Fixed deleting VLAN interface with non-default MTU +* :vytask:`T1505` vyos.config ``return_effective_values()`` function now + correctly returns a list rather than a string \ No newline at end of file diff --git a/docs/changelog/1.2.3.rst b/docs/changelog/1.2.3.rst new file mode 100644 index 00000000..653beec1 --- /dev/null +++ b/docs/changelog/1.2.3.rst @@ -0,0 +1,62 @@ +1.2.3 +===== + +1.2.3 is a maintenance and feature backport release made in September 2019. + +New features +------------ + +* HTTP API +* :vytask:`T1524` "set service dns forwarding allow-from " + option for limiting queries to specific client networks +* :vytask:`T1503` Functions for checking if a commit is in progress +* :vytask:`T1543` "set system contig-mangement commit-archive source-address" + option +* :vytask:`T1554` Intel NIC drivers now support receive side scaling and + multiqueue + +Resolved issues +--------------- + +* :vytask:`T1209` OSPF max-metric values over 100 no longer causes commit + errors +* :vytask:`T1333` Fixes issue with DNS forwarding not performing recursive + lookups on domain specific forwarders +* :vytask:`T1362` Special characters in VRRP passwords are handled correctly +* :vytask:`T1377` BGP weight is applied properly +* :vytask:`T1420` Fixed permission for log files +* :vytask:`T1425` Wireguard interfaces now support /31 addresses +* :vytask:`T1428` Wireguard correctly handles firewall marks +* :vytask:`T1439` DHCPv6 static mappings now work correctly +* :vytask:`T1450` Flood ping commands now works correctly +* :vytask:`T1460` Op mode "show firewall" commands now support counters longer + than 8 digits (T1460) +* :vytask:`T1465` Fixed priority inversion in VTI commands +* :vytask:`T1468` Fixed remote-as check in the BGP route-reflector-client option +* :vytask:`T1472` It's now possible to re-create VRRP groups with RFC + compatibility mode enabled +* :vytask:`T1527` Fixed a typo in DHCPv6 server help strings +* :vytask:`T1529` Unnumbered BGP peers now support VLAN interfaces +* :vytask:`T1530` Fixed "set system syslog global archive file" command +* :vytask:`T1531` Multiple fixes in cluster configuration scripts +* :vytask:`T1537` Fixed missing help text for "service dns" +* :vytask:`T1541` Fixed input validation in DHCPv6 relay options +* :vytask:`T1551` It's now possible to create a QinQ interface and a firewall + assigned to it in one commit +* :vytask:`T1559` URL filtering now uses correct rule database path and works + again +* :vytask:`T1579` "show log vpn ipsec" command works again +* :vytask:`T1576` "show arp interface " command works again +* :vytask:`T1605` Fixed regression in L2TP/IPsec server +* :vytask:`T1613` Netflow/sFlow captures IPv6 traffic correctly +* :vytask:`T1616` "renew dhcpv6" command now works from op mode +* :vytask:`T1642` BGP remove-private-as option iBGP vs eBGP check works + correctly now +* :vytask:`T1540`, :vytask:`T1360`, :vytask:`T1264`, :vytask:`T1623` Multiple + improvements in name servers and hosts configuration handling + +Internals +--------- + +``/etc/resolv.conf`` and ``/etc/hosts`` files are now managed by the +*vyos-hostsd* service that listens on a ZMQ socket for update messages. \ No newline at end of file diff --git a/docs/changelog/1.2.4.rst b/docs/changelog/1.2.4.rst new file mode 100644 index 00000000..397c9bb9 --- /dev/null +++ b/docs/changelog/1.2.4.rst @@ -0,0 +1,65 @@ +1.2.4 +===== + +1.2.4 is a maintenance release made in December 2019. + +Resolved issues +--------------- + +* :vytask:`T258` Can not configure wan load-balancing on vyos-1.2 +* :vytask:`T818` SNMP v3 - remove required engineid from user node +* :vytask:`T1030` Upgrade ddclient from 3.8.2 to 3.9.0 (support Cloudflare API v4) +* :vytask:`T1183` BFD Support via FRR +* :vytask:`T1299` Allow SNMPd to be extended with custom scripts +* :vytask:`T1351` accel-pppoe adding CIDR based IP pool option +* :vytask:`T1391` In route-map set community additive +* :vytask:`T1394` syslog systemd and host_name.py race condition +* :vytask:`T1401` Copying files with the FTP protocol fails if the password contains special characters +* :vytask:`T1421` OpenVPN client push-route stopped working, needs added quotes to fix +* :vytask:`T1430` Add options for custom DHCP client-id and hostname +* :vytask:`T1447` Python subprocess called without import in host_name.py +* :vytask:`T1470` improve output of "show dhcpv6 server leases" +* :vytask:`T1485` Enable 'AdvIntervalOpt' option in for radvd.conf +* :vytask:`T1496` Separate rolling release and LTS kernel builds +* :vytask:`T1560` "set load-balancing wan rule 0" causes segfault and prevents load balancing from starting +* :vytask:`T1568` strip-private command improvement for additional masking of IPv6 and MAC address +* :vytask:`T1578` completion offers "show table", but show table does not exist +* :vytask:`T1593` Support ip6gre +* :vytask:`T1597` /usr/sbin/rsyslogd after deleting "system syslog" +* :vytask:`T1638` vyos-hostsd not setting system domain name +* :vytask:`T1678` hostfile-update missing line feed +* :vytask:`T1694` NTPd: Do not listen on all interfaces by default +* :vytask:`T1701` Delete domain-name and domain-search won't work +* :vytask:`T1705` High CPU usage by bgpd when snmp is active +* :vytask:`T1707` DHCP static mapping and exclude address not working +* :vytask:`T1708` Update Rolling Release Kernel to 4.19.76 +* :vytask:`T1709` Update WireGuard to 0.0.20190913 +* :vytask:`T1716` Update Intel NIC drivers to recent versions +* :vytask:`T1726` Update Linux Firmware binaries to a more recent version 2019-03-14 -> 2019-10-07 +* :vytask:`T1728` Update Linux Kernel to 4.19.79 +* :vytask:`T1737` SNMP tab completion missing +* :vytask:`T1738` Copy SNMP configuration from node to node raises exception +* :vytask:`T1740` Broken OSPFv2 virtual-link authentication +* :vytask:`T1742` NHRP unable to commit. +* :vytask:`T1745` dhcp-server commit fails with "DHCP range stop address x must be greater or equal to the range start address y!" when static mapping has same IP as range stop +* :vytask:`T1749` numeric validator doesn't support multiple ranges +* :vytask:`T1769` Remove complex SNMPv3 Transport Security Model (TSM) +* :vytask:`T1772` constraints in XML are partially broken +* :vytask:`T1778` Kilobits/Megabits difference in configuration Vyos/FRR +* :vytask:`T1780` Adding ipsec ike closeaction +* :vytask:`T1786` disable-dhcp-nameservers is missed in current host_name.py implementation +* :vytask:`T1788` Intel QAT (QuickAssist Technology ) implementation +* :vytask:`T1792` Update WireGuard to Debian release 0.0.20191012-1 +* :vytask:`T1800` Update Linux Kernel to v4.19.84 +* :vytask:`T1809` Wireless: SSID scan does not work in AP mode +* :vytask:`T1811` Upgrade from 1.1.8: Config file migration failed: module=l2tp +* :vytask:`T1812` DHCP: hostnames of clients not resolving after update v1.2.3 -> 1.2-rolling +* :vytask:`T1819` Reboot kills SNMPv3 configuration +* :vytask:`T1822` Priority inversion wireless interface dhcpv6 +* :vytask:`T1825` Improve DHCP configuration error message +* :vytask:`T1836` import-conf-mode-commands in vyos-1x/scripts fails to create an xml +* :vytask:`T1839` LLDP shows "VyOS unknown" instead of "VyOS" +* :vytask:`T1841` PPP ipv6-up.d direcotry missing +* :vytask:`T1893` igmp-proxy: Do not allow adding unknown interface +* :vytask:`T1903` Implementation udev predefined interface naming +* :vytask:`T1904` update eth1 and eth2 link files for the vep4600 \ No newline at end of file diff --git a/docs/changelog/1.2.5.rst b/docs/changelog/1.2.5.rst new file mode 100644 index 00000000..231e92f2 --- /dev/null +++ b/docs/changelog/1.2.5.rst @@ -0,0 +1,60 @@ +1.2.5 +===== + +1.2.5 is a maintenance release made in April 2020. + +Resolved issues +--------------- + +* :vytask:`1020` OSPF Stops distributing default route after a while +* :vytask:`1228` pppoe default-route force option not working (Rel 1.2.0-rc11) +* :vytask:`1301` bgp peer-groups don't work when "no-ipv4-unicast" is enabled. +* :vytask:`1341` Adding rate-limiter for pppoe server users +* :vytask:`1376` Incorrect DHCP lease counting +* :vytask:`1392` Large firewall rulesets cause the system to lose configuration and crash at startup +* :vytask:`1416` 2 dhcp server run in failover mode can't sync hostname with each other +* :vytask:`1452` accel-pppoe - add vendor option to shaper +* :vytask:`1490` BGP configuration (is lost|not applied) when updating 1.1.8 -> 1.2.1 +* :vytask:`1780` Adding ipsec ike closeaction +* :vytask:`1803` Unbind NTP while it's not requested... +* :vytask:`1821` "authentication mode radius" has no effect for PPPoE server +* :vytask:`1827` Increase default gc_thresh +* :vytask:`1828` Missing completion helper for "set system syslog host 192.0.2.1 facility all protocol" +* :vytask:`1832` radvd adding feature DNSSL branch.example.com example.com to existing package +* :vytask:`1837` PPPoE unrecognized option 'replacedefaultroute' +* :vytask:`1851` wireguard - changing the pubkey on an existing peer seems to destroy the running config. +* :vytask:`1858` l2tp: Delete depricated outside-nexthop and add gateway-address +* :vytask:`1864` Lower IPSec DPD timeout lower limit from 10s -> 2s +* :vytask:`1879` Extend Dynamic DNS XML definition value help strings and validators +* :vytask:`1881` Execute permissions are removed from custom SNMP scripts at commit time +* :vytask:`1884` Keeping VRRP transition-script native behaviour and adding stop-script +* :vytask:`1891` Router announcements broken on boot +* :vytask:`1900` Enable SNMP for VRRP. +* :vytask:`1902` Add redistribute non main table in bgp +* :vytask:`1909` Incorrect behaviour of static routes with overlapping networks +* :vytask:`1913` "system ipv6 blacklist" command has no effect +* :vytask:`1914` IPv6 multipath hash policy does not apply +* :vytask:`1917` Update WireGuard to Debian release 0.0.20191219-1 +* :vytask:`1934` Change default hostname when deploy from OVA without params. +* :vytask:`1935` NIC identification and usage problem in Hyper-V environments +* :vytask:`1936` pppoe-server CLI control features +* :vytask:`1964` SNMP Script-extensions allows names with spaces, but commit fails +* :vytask:`1967` BGP parameter "enforce-first-as" does not work anymore +* :vytask:`1970` Correct adding interfaces on boot +* :vytask:`1971` Missing modules in initrd.img for PXE boot +* :vytask:`1998` Update FRR to 7.3 +* :vytask:`2001` Error when router reboot +* :vytask:`2032` Monitor bandwidth bits +* :vytask:`2059` Set source-validation on bond vif don't work +* :vytask:`2066` PPPoE interface can be created multiple times - last wins +* :vytask:`2069` PPPoE-client does not works with service-name option +* :vytask:`2077` ISO build from crux branch is failing +* :vytask:`2079` Update Linux Kernel to v4.19.106 +* :vytask:`2087` Add maxfail 0 option to pppoe configuration. +* :vytask:`2100` BGP route adverisement wih checks rib +* :vytask:`2120` "reset vpn ipsec-peer" doesn't work with named peers +* :vytask:`2197` Cant add vif-s interface into a bridge +* :vytask:`2228` WireGuard does not allow ports < 1024 to be used +* :vytask:`2252` HTTP API add system image can return '504 Gateway Time-out' +* :vytask:`2272` Set system flow-accounting disable-imt has syntax error +* :vytask:`2276` PPPoE server vulnerability \ No newline at end of file diff --git a/docs/changelog/index.rst b/docs/changelog/index.rst new file mode 100644 index 00000000..26262932 --- /dev/null +++ b/docs/changelog/index.rst @@ -0,0 +1,14 @@ +######### +Changelog +######### + + +.. toctree:: + :maxdepth: 1 + :includehidden: + + 1.2.5 + 1.2.4 + 1.2.3 + 1.2.2 + 1.2.1 diff --git a/docs/cli.rst b/docs/cli.rst index 4694cc5d..b138b18b 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -1,14 +1,14 @@ .. _cli: -### -CLI -### +##################### +Comand Line Interface +##################### The VyOS :abbr:`CLI (Command-Line Interface)` comprises an operational and a configuration mode. Operational Mode -================ +################ Operational mode allows for commands to perform operational system tasks and view system and service status, while configuration mode allows for the @@ -73,7 +73,7 @@ When viewing in page mode the following commands are available: in the event that the output has lines which exceed the terminal size. Configuration Mode -================== +################## The list of all operational level commands is available at :ref:`configuration_level_commands`. diff --git a/docs/contributing/documentation.rst b/docs/contributing/documentation.rst index e8d1dba5..9dd0c495 100644 --- a/docs/contributing/documentation.rst +++ b/docs/contributing/documentation.rst @@ -1,7 +1,8 @@ .. _documentation: +############# Documentation -============= +############# As most software projects we also have a lack in documentation. We encourage every VyOS user to help us improve our documentation. This will not only be @@ -15,7 +16,7 @@ guide how to do so. documentation. Forking Workflow ----------------- +================ The Forking Workflow is fundamentally different than other popular Git workflows. Instead of using a single server-side repository to act as the @@ -102,17 +103,20 @@ access to the official codebase. push origin master`` Style Guide ------------ +=========== -Sections -^^^^^^^^ +Formating and Sphinxmarkup +-------------------------- + +TOC Level +^^^^^^^^^^ We use the following syntax for Headlines. .. code-block:: none ##### - Parts + Title ##### ******** @@ -159,16 +163,17 @@ render the documentation. cfgcmd """""" -When documenting CLI commands use the ``.. cfgcmd::`` directive for all -configuration mode commands. An explanation of the described command should be -added below this statement. +When documenting CLI commands use the ``.. cfgcmd::`` directive +for all configuration mode commands. An explanation of the described command +should be added below this statement. +Replace all variable contents with or somthing similar. With those custom commands it will be possible to render them in a more descriptive way in the resulting HTML/PDF manual. .. code-block:: none - .. cfgcmd:: set protocols static arp 192.0.2.100 hwaddr 00:53:27:de:23:aa + .. cfgcmd:: protocols static arp hwaddr This will configure a static ARP entry always resolving `192.0.2.100` to `00:53:27:de:23:aa`. @@ -250,6 +255,70 @@ URL. This is heavily used in the :ref:`release-notes` section. * :vytask:`T1605` Fixed regression in L2TP/IPsec server * :vytask:`T1613` Netflow/sFlow captures IPv6 traffic correctly +Page content +------------ + +The documentation have 3 different types of pages, the same kind of pages must +have the same structure to achieve a recognition factor. + +For all *.rst files must follow the same TOC Level syntax and have to start with + +.. code-block:: + + ##### + Titel + ##### + +Configuration mode pages +^^^^^^^^^^^^^^^^^^^^^^^^ + +A configuration mode article covers a specific level of a command. +The exact level depends on the command. + +For example: + + * ``set zone-policy`` is written in ``zone-policy/index.rst`` + * ``set interfaces ethernet`` is written in ``interfaces/ethernet.rst`` + +The article starts with a short intruducing about the command or the technologie. +Include some helpfull links or background informations. + +After this a optional section follows. Some commands have requirements like the +compatible hardware (e.g. Wifi) or some commands you have to set before. For +example it is recommended to set a route-map before configure bgp. + +In the configuration part of the page all possible confiuration options +should be documented. Use ``.. cfgcmd::`` like described above. + +Related Operation command must be documented in the next part of the articel. +Use ``::opcmd..`` for these commands. + +If there some troubleshooting guides releated to the commands. Explain it in the +next optional part. + +Examples: + + * ssh + + + +Operation mode pages +^^^^^^^^^^^^^^^^^^^^ + +Operation mode commands, which didn't fit in a related configuraton mode command +must documented in this part of the documentation. + +.. todo:: + + create structure + + +Anything else +^^^^^^^^^^^^^ + +Anything else what is not a configuration or a operation command have no +predefined structure. + .. _Sphinx-doc: https://www.sphinx-doc.org .. _reStructuredText: http://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst new file mode 100644 index 00000000..c3bb2688 --- /dev/null +++ b/docs/contributing/index.rst @@ -0,0 +1,13 @@ +############ +Contributing +############ + +.. toctree:: + :maxdepth: 2 + + build-vyos + debugging + development + documentation + issues-features + upstream-packages \ No newline at end of file diff --git a/docs/copyright.rst b/docs/copyright.rst new file mode 100644 index 00000000..beebc2a2 --- /dev/null +++ b/docs/copyright.rst @@ -0,0 +1,19 @@ +################ +Copyright Notice +################ + +Copyright (C) 2018-2020 VyOS maintainers and contributors + +Permission is granted to make and distribute verbatim copies of this manual +provided the copyright notice and this permission notice are preserved on all +copies. + +Permission is granted to copy and distribute modified versions of this manual +under the conditions for verbatim copying, provided that the entire resulting +derived work is distributed under the terms of a permission notice identical +to this one. + +Permission is granted to copy and distribute translations of this manual into +another language, under the above conditions for modified versions, except that +this permission notice may be stated in a translation approved by the VyOS +maintainers. \ No newline at end of file diff --git a/docs/draw.io/pbr_example_1.drawio b/docs/draw.io/pbr_example_1.drawio deleted file mode 100644 index 0d496572..00000000 --- a/docs/draw.io/pbr_example_1.drawio +++ /dev/null @@ -1 +0,0 @@ -7VrbcqM4EP0aP4ZCgLk8xkk8u1UzW97K7FyepmRQsGoEYoUc2/P1K4G4CLBNJo7j2rLzAGpJrVafPq2WnYl9l2w/MJitPtEIkYllRtuJfT+xLMtzTPGQkl0pCQKnFMQMR6UINIJH/AspoZoXr3GEcm0gp5RwnOnCkKYpCrkmg4zRjT7siRJ91QzGqCd4DCHpS7/iiK+UFJhm0/EHwvFKLe1PVccShj9jRtepWm9i2U/Fp+xOYKVLjc9XMKKblsh+mNh3jFJeviXbO0Skbyu3lfPme3pruxlK+ZgJn4MU/ArY39bX3eKfT37yffHh8w2wSzXPkKxRtQ+XCIWzCD9Lq/lOecr9dy1NnXG05TeQ4Did2LdiBEFPXDxET+H+lN/kBciyD9jZtpkp3mL1LFbIM5h2ZcuuQGoctGPUUn8+LkClSbimVKYvIMS9RYVsyDghLryiS9/HUa/zCwgswzSAMcI5YxxhaZZYK54Q8QZE3zNiHAu2fYRLRBY0xxxT4Y/7JeWcJmKActB9KMIYMSEgcuSsJtcdJZQVait6NUpv1VxOM+klzujPmsRWLWlpME3fnEsEnjAhQ5prkspBEcxXKFIN0ZPJ7SXbWCZCA9PcM7DISrkRErqOaj9I49B2L0lBTX2RUhFNEGc7MURNuAkCv5yj0qkTlM1NKzf5SrZqpSVgqbQLVT6Ma91NThAvKi28JEU4r04RrLDzgnOEdZwG58kRJ/bUKZKEZYzwzjVJnDNJeO6lJQnLHUgSHcBRJAov1cxRnIjdPjSiGUqjW1nPSZgJzHMcCmErSNAW82+t9+/S58ZUte63CoKisVMNGa0tBGf2fO66fWSjKfIjZygWXHdmzee9uLFrIOWmDsMofEDXLEQHvBcMw92Csyo622hWMoYI5PhZN2MIYbXCguIiK1TR5HeiyfV94VZNS7kDNbFdY/Z0TXVdoK+LQxYj3tMlsIe71rBMDsgPmd1Zyp0GaqnR1gnz9CnipbSjYUKNxyvIEZyNHOb/jxzWu5LD87wqgOs48w3fbj6/SxXPORtVukv1qPI2cQ+s43HfPTFDnIfUEIe6OOdz9dRDXTtwO7Fq2q4feEOx2hzevQLgaPUxXEkUhUf75G9qgpAmkqA1y+YwwUT6/gtiEUyhEqsvQ4B1qruDr0eq5Vcwt9li+85AZVCVCyevDGxwPAhkEZft9YD65gcuq+Hmiz3jAZ0AU98Z8AzwBxIJqDLJ6WumnmO+fLz9C9RX8iUbLvH3lfMbZbUs6FPKEkiGS3rg+obA2xD7msuCcE8R38Fos8IcPWawyNUbwVWdlSPZoLMPjOOHM1CLT+Vfj+gpTVE1WZkO9hJ4FOUOxPTBM+nMsTR0Rx+VaQU4WZFrf8A0+pEhhrMVYpDkRtYpMS4j754cM6XGcbUEMXCj8vw+oN5b4TniOnXF8xCeUx3P6TvjaY8ohd78FARmtb9LOgb7l6PiGDTPcwz612Pw9yl4/Gp25liqflS85s0Xg3aZ5yAYcXu4AnoRB6FoNj9ml18hNP8xYD/8Bw== \ No newline at end of file diff --git a/docs/draw.io/vpn_s2s_ikev2.drawio b/docs/draw.io/vpn_s2s_ikev2.drawio deleted file mode 100644 index b240c191..00000000 --- a/docs/draw.io/vpn_s2s_ikev2.drawio +++ /dev/null @@ -1 +0,0 @@ -7Zrdk6I4EMD/Gh+lSMLn4zgz7j7cVk3V1H3svWxFiJhaIB7EUfevv4QEIYCje6eOW4XzIOmQTtL5ddP0OEGP2e5TgderLywm6QTa8W6CniYQIoCA+JKSvZJA2/WVJClorGSgEbzSH0QLbS3d0JiUxo2csZTTtSmMWJ6TiBsyXBRsa962ZKk56xonpCd4jXDal/5JY77SUmDbTcdnQpOVnjpwdccCR9+Tgm1yPd8EomX1Ud0ZrnXp+8sVjtm2JULPE/RYMMbVVbZ7JKk0bm02NW5+pPew7oLk/JwBv/tf4d9PP749rV+/8DAihK2iqRwg1bzhdEPqfVSr5fvaQtUeidQCJmi2XVFOXtc4kr1bAYWQrXiW6m6tjhSc7I4uFBy2L7giLCO82Itb9ICp43pqjGZqilytZNuckOM4SrZqHQ6qccSaiuSgvbGMuNDG+RlDgTs0FLADdHeWOsNQwhXW8jLbJTKqWBEtI2YJ83FSlPrbtFaMy1VlWVs0ljRNH1nKikobspEXhL6Ql7xg30mrR/tj3VP7tzDpTBqeiijwG16Q9IWVlFOWi74F45xlrRseUprIDs7kATZHLBdycGnZiFhGo3qFLOdznNFUnssfpIhxjrVYR0AAL8aA65gMwNDtMYCCAQZAEF7LW0YGbsmAg+4PATQicEsEfMe3XBOCAKCPhsA5DQGJRTqmmyVJMrHh50Y0I3n8ILM80ZuznJg4kB3lf0lbi62r1ldteXn9tGs39q0zabExQ/O55/Vpil0SxM4QTZ43g/N5jyakJ3ohBRXGk+SqyXNhSLXI6rCrdrVMK6ybzUqr1r7d6uuL51SeQtVS5pQ2fB8cYXK2KSJy+rnNcZEQfsqx+yC2IKsz5DZjtawgKeb0zVzuEHd6hhdGxUYazgMPWQFqPp30B3qmRrVrraSdHPf0hu/p9UPf8lof15xF2aw3iwAX71u3reUN5bubOxLHjy+7O8LxT4zwbfDuCHGh1t14/eGU/3sgcMdA0AoEQXDPgQD+EoHA8aDhsHbHZcWbutVx07ODAfKBBfruXqt2PTAQKy4dDKADf9K1nbqmclPXBkOZnpeK454txEXCKzqVQPqc4fXePxtWd0zLKid6EDeAYL1rOmstwIcWCCzRbYmNzqFTqxUNpdmcTYhbK+iEG5FrcTOImA6ug0w7GmgR1qlgJDyrSlC7OWJG47iKWUMlADN1vETq13sGuHY/+weO2/fFujR1+RrAUOJ3FSYs6I4YqAd7FwOvrvu0a0H+LSkYeupfhwIZ+UYI4DSEdvc1EDWiDwPBG8PBrUlw7LsLB/4YDm4MAewWBg9l/w+DILh5tgjHbLH9bhPeXbYYHkXi/xHwxmkTCBZF98DLNc6PK9/qnUv1OSsynA4gZlvyT25f+tWBI6W5h5dJXYewE/8uPLPibJYiwOSsGrQz6VU9lq78O4q5HKyXDgaQVkXyS9AK7O7LdwgGshlYv/0blQZ0JV5rR/hlgUUjsNcCtle1Ce2PpvUK7+LQGcK3qHYzPmWrUlwv8Rp8CxsokF7tMQuv8Do+DEJKliMH+vnldP9FNZSBXwYD0Wx+TqbKu82P9tDzvw== \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index ab9d3f66..3322bf8d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,102 +6,44 @@ VyOS User Guide .. toctree:: - :caption: Introduction - :name: intro :maxdepth: 2 + :hidden: + :caption: FIND CAPTION NAME - about - history - install - cli + introducing/about + introducing/history + introducing/releases + changelog/index + +.. toctree:: + :maxdepth: 2 + :hidden: + :includehidden: + :caption: first steps + + installation/index quick-start + cli - + .. toctree:: - :caption: Basic Configuration - :name: basics :maxdepth: 2 + :hidden: + :includehidden: + :caption: Adminguide - configuration-overview - interfaces/basic-index - system/basic-index - image-mgmt + configuration/index + operation/index + automation/index + troubleshooting/index + configexamples/index .. toctree:: - :caption: Advanced Configuration - :name: advanced :maxdepth: 2 - - interfaces/advanced-index - system/advanced-index - services/index - firewall - routing/index - vrf - nat - nptv6 - qos - high-availability - vpn/index - load-balancing - command-list-configuration - - -.. toctree:: - :caption: System Operation - :name: system-operation - :maxdepth: 2 - - information - troubleshooting - command-list-operation - - -.. toctree:: - :caption: Appendix - :name: appendix - :maxdepth: 2 - - appendix/release-notes - appendix/examples/index - appendix/vyos-on-baremetal - appendix/virtual/index - appendix/vyos-on-clouds - appendix/migrate-from-vyatta - appendix/command-scripting - appendix/http-api - - -.. toctree:: + :hidden: + :includehidden: :caption: Contributing - :name: contributing - :maxdepth: 2 - contributing/build-vyos - contributing/upstream-packages - contributing/issues-features - contributing/development - contributing/debugging - contributing/documentation - - -################ -Copyright Notice -################ - -Copyright (C) 2018-2020 VyOS maintainers and contributors - -Permission is granted to make and distribute verbatim copies of this manual -provided the copyright notice and this permission notice are preserved on all -copies. - -Permission is granted to copy and distribute modified versions of this manual -under the conditions for verbatim copying, provided that the entire resulting -derived work is distributed under the terms of a permission notice identical -to this one. - -Permission is granted to copy and distribute translations of this manual into -another language, under the above conditions for modified versions, except that -this permission notice may be stated in a translation approved by the VyOS -maintainers. + contributing/index + copyright diff --git a/docs/installation/index.rst b/docs/installation/index.rst new file mode 100644 index 00000000..af265121 --- /dev/null +++ b/docs/installation/index.rst @@ -0,0 +1,18 @@ +################################# +Installation and Image Management +################################# + + + +.. toctree:: + :maxdepth: 2 + :caption: Content + + install + iso + virtual/index + cloud/index + update + image + migrate-from-vyatta + ../vyos-on-baremetal \ No newline at end of file diff --git a/docs/install.rst b/docs/installation/install.rst similarity index 100% rename from docs/install.rst rename to docs/installation/install.rst diff --git a/docs/about.rst b/docs/introducing/about.rst similarity index 86% rename from docs/about.rst rename to docs/introducing/about.rst index 383c95eb..0411344b 100644 --- a/docs/about.rst +++ b/docs/introducing/about.rst @@ -8,7 +8,7 @@ VyOS is an open source network operating system based on Debian GNU/Linux. VyOS provides a free routing platform that competes directly with other commercially available solutions from well known network providers. Because -VyOS is run on standard amd64, i586 and ARM systems, it can be used +VyOS is run on standard amd64, i586 and ARM systems, it is able to be used as a router and firewall platform for cloud deployments. We use multiple live versions of our manual hosted thankfully by @@ -16,7 +16,7 @@ https://readthedocs.org. We will provide one version of the manual for every VyOS major version starting with VyOS 1.2 which will receive Long-term support (LTS). -The manual version is selected/specified by its Git branch name. You can +The manual version is selected/specified by it's Git branch name. You can switch between versions of the documentation by selecting the appropriate branch on the bottom left corner. diff --git a/docs/history.rst b/docs/introducing/history.rst similarity index 100% rename from docs/history.rst rename to docs/introducing/history.rst diff --git a/docs/introducing/releases.rst b/docs/introducing/releases.rst new file mode 100644 index 00000000..6d95c4bc --- /dev/null +++ b/docs/introducing/releases.rst @@ -0,0 +1,29 @@ +.. _release: + +######## +Releases +######## + +Rolling Release +############### + +rolling rolling + +LTS +### + +lts lts lts + + +old LTS +======= + +old LTSLTSLTSLTS + +even older LTS +-------------- + +even older LTS even older LTS +even older LTS even older LTS even older LTS even older LTS even older LTS + + diff --git a/docs/troubleshooting.rst b/docs/troubleshooting/index.rst similarity index 100% rename from docs/troubleshooting.rst rename to docs/troubleshooting/index.rst From a6c226d4b4e79c07121b0a609d2fb78cae70f3b0 Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 19:24:16 +0100 Subject: [PATCH 13/28] arange installation and image management --- docs/appendix/virtual/index.rst | 12 -- docs/appendix/vyos-on-clouds.rst | 173 ------------------ docs/installation/cloud/aws.rst | 54 ++++++ docs/installation/cloud/azure.rst | 53 ++++++ docs/installation/cloud/gcp.rst | 55 ++++++ docs/installation/cloud/index.rst | 13 ++ docs/installation/cloud/oracel.rst | 8 + .../image.rst} | 78 -------- docs/installation/index.rst | 3 +- docs/installation/iso.rst | 2 + .../migrate-from-vyatta.rst | 0 docs/installation/upate.rst | 79 ++++++++ docs/installation/virtual/eve-ng.rst | 8 + .../virtual/gns3.rst} | 0 docs/installation/virtual/index.rst | 12 ++ .../virtual/libvirt.rst | 0 docs/installation/virtual/proxmox.rst | 8 + .../virtual/vmware.rst} | 0 .../vyos-on-baremetal.rst | 0 19 files changed, 294 insertions(+), 264 deletions(-) delete mode 100644 docs/appendix/virtual/index.rst delete mode 100644 docs/appendix/vyos-on-clouds.rst create mode 100644 docs/installation/cloud/aws.rst create mode 100644 docs/installation/cloud/azure.rst create mode 100644 docs/installation/cloud/gcp.rst create mode 100644 docs/installation/cloud/index.rst create mode 100644 docs/installation/cloud/oracel.rst rename docs/{image-mgmt.rst => installation/image.rst} (51%) create mode 100644 docs/installation/iso.rst rename docs/{appendix => installation}/migrate-from-vyatta.rst (100%) create mode 100644 docs/installation/upate.rst create mode 100644 docs/installation/virtual/eve-ng.rst rename docs/{appendix/virtual/vyos-on-gns3.rst => installation/virtual/gns3.rst} (100%) create mode 100644 docs/installation/virtual/index.rst rename docs/{appendix => installation}/virtual/libvirt.rst (100%) create mode 100644 docs/installation/virtual/proxmox.rst rename docs/{appendix/virtual/vyos-on-vmware.rst => installation/virtual/vmware.rst} (100%) rename docs/{appendix => installation}/vyos-on-baremetal.rst (100%) diff --git a/docs/appendix/virtual/index.rst b/docs/appendix/virtual/index.rst deleted file mode 100644 index 7ede37b5..00000000 --- a/docs/appendix/virtual/index.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _virtual: - -Running on Virtual Environments -=============================== - - -.. toctree:: - :maxdepth: 2 - - libvirt - vyos-on-vmware - vyos-on-gns3 diff --git a/docs/appendix/vyos-on-clouds.rst b/docs/appendix/vyos-on-clouds.rst deleted file mode 100644 index 33b7011e..00000000 --- a/docs/appendix/vyos-on-clouds.rst +++ /dev/null @@ -1,173 +0,0 @@ -.. _vyos-on-clouds: - -Running on Clouds -################# - -Amazon AWS -********** - -Deploy VM ---------- - -Deploy VyOS on Amazon :abbr:`AWS (Amazon Web Services)` - -1. Click to ``Instances`` and ``Launch Instance`` - -.. figure:: /_static/images/cloud-aws-01.png - -2. On the marketplace search "VyOS" - -.. figure:: /_static/images/cloud-aws-02.png - -3. Choose the instance type. Minimum recommendation start from ``m3.medium`` - -.. figure:: /_static/images/cloud-aws-03.png - -4. Configure instance for your requirements. Select number of instances / network / subnet - -.. figure:: /_static/images/cloud-aws-04.png - -5. Additional storage. You can remove additional storage ``/dev/sdb``. First root device will be ``/dev/xvda``. You can skeep this step. - -.. figure:: /_static/images/cloud-aws-05.png - -6. Configure Security Group. It's recommended that you configure ssh access only from certain address sources. Or permit any (by default). - -.. figure:: /_static/images/cloud-aws-06.png - -7. Select SSH key pair and click ``Launch Instances`` - -.. figure:: /_static/images/cloud-aws-07.png - -8. Find out your public IP address. - -.. figure:: /_static/images/cloud-aws-08.png - -9. Connect to the instance by SSH key. - - .. code-block:: none - - ssh -i ~/.ssh/amazon.pem vyos@203.0.113.3 - vyos@ip-192-0-2-10:~$ - - - - -References ----------- -https://console.aws.amazon.com/ - -Azure -***** - -Deploy VM ---------- - -Deploy VyOS on Azure. - -1. Go to the Azure services and Click to **Add new Virtual machine** - -2. Choose vm name, resource group, region and click **Browse all public and private images** - -.. figure:: /_static/images/cloud-azure-01.png - -3. On the marketplace search ``VyOS`` - -.. figure:: /_static/images/cloud-azure-02.png - -4. Generate new SSH key pair or use existing. - -.. figure:: /_static/images/cloud-azure-03.png - -5. Define network, subnet, Public IP. Or it will be created by default. - -.. figure:: /_static/images/cloud-azure-04.png - -6. Click ``Review + create``. After fiew second your deployment will be complete - -.. figure:: /_static/images/cloud-azure-05.png - -7. Click to your new vm and find out your Public IP address. - -.. figure:: /_static/images/cloud-azure-06.png - -8. Connect to the instance by SSH key. - - .. code-block:: none - - ssh -i ~/.ssh/vyos_azure vyos@203.0.113.3 - vyos@vyos-doc-r1:~$ - -Add interface -------------- - -If instance was deployed with one **eth0** ``WAN`` interface and want to add new one. -To add new interface an example **eth1** ``LAN`` you need shutdown the instance. Attach the interface in the Azure portal and then start the instance. - -.. NOTE:: Azure does not allow you attach interface when the instance in the **Running** state. - -References ----------- -https://azure.microsoft.com - -Google Cloud Platform -********************* - -Deploy VM ---------- - -To deploy VyOS on GCP (Google Cloud Platform) - -1. Generate SSH key pair type **ssh-rsa** from the host that will connect to VyOS. - - Example: - - .. code-block:: none - - ssh-keygen -t rsa -f ~/.ssh/vyos_gcp -C "vyos@mypc" - - -.. NOTE:: In name "vyos@mypc" The first value must be "**vyos**". Because default user is vyos and google api uses this option. - - -2. Open GCP console and navigate to the menu **Metadata**. Choose **SSH Keys** and click ``edit``. - -.. figure:: /_static/images/cloud-gcp-01.png - - -Click **Add item** and paste your public ssh key. Click ``Save``. - -.. figure:: /_static/images/cloud-gcp-02.png - - -2. On marketplace search "VyOS" - -3. Change Deployment name/Zone/Machine type and click ``Deploy`` - -.. figure:: /_static/images/cloud-gcp-03.png - -4. After fiew seconds click to ``instance`` - -.. figure:: /_static/images/cloud-gcp-04.png - -5. Find out your external IP address - -.. figure:: /_static/images/cloud-gcp-05.png - -6. Connect to the instance. SSH key was generated in the first step. - - .. code-block:: none - - ssh -i ~/.ssh/vyos_gcp vyos@203.0.113.3 - vyos@vyos-r1-vm:~$ - -References ----------- -https://console.cloud.google.com/ - -Oracle -***************** - -References ----------- -https://www.oracle.com/cloud/ diff --git a/docs/installation/cloud/aws.rst b/docs/installation/cloud/aws.rst new file mode 100644 index 00000000..33684bb0 --- /dev/null +++ b/docs/installation/cloud/aws.rst @@ -0,0 +1,54 @@ +########## +Amazon AWS +########## + +Deploy VM +--------- + +Deploy VyOS on Amazon :abbr:`AWS (Amazon Web Services)` + +1. Click to ``Instances`` and ``Launch Instance`` + +.. figure:: /_static/images/cloud-aws-01.png + +2. On the marketplace search "VyOS" + +.. figure:: /_static/images/cloud-aws-02.png + +3. Choose the instance type. Minimum recommendation start from ``m3.medium`` + +.. figure:: /_static/images/cloud-aws-03.png + +4. Configure instance for your requirements. Select number of instances / network / subnet + +.. figure:: /_static/images/cloud-aws-04.png + +5. Additional storage. You can remove additional storage ``/dev/sdb``. First root device will be ``/dev/xvda``. You can skeep this step. + +.. figure:: /_static/images/cloud-aws-05.png + +6. Configure Security Group. It's recommended that you configure ssh access only from certain address sources. Or permit any (by default). + +.. figure:: /_static/images/cloud-aws-06.png + +7. Select SSH key pair and click ``Launch Instances`` + +.. figure:: /_static/images/cloud-aws-07.png + +8. Find out your public IP address. + +.. figure:: /_static/images/cloud-aws-08.png + +9. Connect to the instance by SSH key. + + .. code-block:: none + + ssh -i ~/.ssh/amazon.pem vyos@203.0.113.3 + vyos@ip-192-0-2-10:~$ + + + + +References +---------- +https://console.aws.amazon.com/ \ No newline at end of file diff --git a/docs/installation/cloud/azure.rst b/docs/installation/cloud/azure.rst new file mode 100644 index 00000000..39206f3b --- /dev/null +++ b/docs/installation/cloud/azure.rst @@ -0,0 +1,53 @@ +##### +Azure +##### + +Deploy VM +--------- + +Deploy VyOS on Azure. + +1. Go to the Azure services and Click to **Add new Virtual machine** + +2. Choose vm name, resource group, region and click **Browse all public and private images** + +.. figure:: /_static/images/cloud-azure-01.png + +3. On the marketplace search ``VyOS`` + +.. figure:: /_static/images/cloud-azure-02.png + +4. Generate new SSH key pair or use existing. + +.. figure:: /_static/images/cloud-azure-03.png + +5. Define network, subnet, Public IP. Or it will be created by default. + +.. figure:: /_static/images/cloud-azure-04.png + +6. Click ``Review + create``. After fiew second your deployment will be complete + +.. figure:: /_static/images/cloud-azure-05.png + +7. Click to your new vm and find out your Public IP address. + +.. figure:: /_static/images/cloud-azure-06.png + +8. Connect to the instance by SSH key. + + .. code-block:: none + + ssh -i ~/.ssh/vyos_azure vyos@203.0.113.3 + vyos@vyos-doc-r1:~$ + +Add interface +------------- + +If instance was deployed with one **eth0** ``WAN`` interface and want to add new one. +To add new interface an example **eth1** ``LAN`` you need shutdown the instance. Attach the interface in the Azure portal and then start the instance. + +.. NOTE:: Azure does not allow you attach interface when the instance in the **Running** state. + +References +---------- +https://azure.microsoft.com diff --git a/docs/installation/cloud/gcp.rst b/docs/installation/cloud/gcp.rst new file mode 100644 index 00000000..66e75704 --- /dev/null +++ b/docs/installation/cloud/gcp.rst @@ -0,0 +1,55 @@ +##################### +Google Cloud Platform +##################### + +Deploy VM +--------- + +To deploy VyOS on GCP (Google Cloud Platform) + +1. Generate SSH key pair type **ssh-rsa** from the host that will connect to VyOS. + + Example: + + .. code-block:: none + + ssh-keygen -t rsa -f ~/.ssh/vyos_gcp -C "vyos@mypc" + + +.. NOTE:: In name "vyos@mypc" The first value must be "**vyos**". Because default user is vyos and google api uses this option. + + +2. Open GCP console and navigate to the menu **Metadata**. Choose **SSH Keys** and click ``edit``. + +.. figure:: /_static/images/cloud-gcp-01.png + + +Click **Add item** and paste your public ssh key. Click ``Save``. + +.. figure:: /_static/images/cloud-gcp-02.png + + +2. On marketplace search "VyOS" + +3. Change Deployment name/Zone/Machine type and click ``Deploy`` + +.. figure:: /_static/images/cloud-gcp-03.png + +4. After fiew seconds click to ``instance`` + +.. figure:: /_static/images/cloud-gcp-04.png + +5. Find out your external IP address + +.. figure:: /_static/images/cloud-gcp-05.png + +6. Connect to the instance. SSH key was generated in the first step. + + .. code-block:: none + + ssh -i ~/.ssh/vyos_gcp vyos@203.0.113.3 + vyos@vyos-r1-vm:~$ + +References +---------- +https://console.cloud.google.com/ \ No newline at end of file diff --git a/docs/installation/cloud/index.rst b/docs/installation/cloud/index.rst new file mode 100644 index 00000000..5236f092 --- /dev/null +++ b/docs/installation/cloud/index.rst @@ -0,0 +1,13 @@ +################################## +Running VyOS in Cloud Environments +################################## + + + +.. toctree:: + :caption: Content + + aws + azure + gcp + oracel \ No newline at end of file diff --git a/docs/installation/cloud/oracel.rst b/docs/installation/cloud/oracel.rst new file mode 100644 index 00000000..72c40127 --- /dev/null +++ b/docs/installation/cloud/oracel.rst @@ -0,0 +1,8 @@ +###### +Oracle +###### + + +References +---------- +https://www.oracle.com/cloud/ \ No newline at end of file diff --git a/docs/image-mgmt.rst b/docs/installation/image.rst similarity index 51% rename from docs/image-mgmt.rst rename to docs/installation/image.rst index 143d02b2..074a0245 100644 --- a/docs/image-mgmt.rst +++ b/docs/installation/image.rst @@ -90,85 +90,7 @@ configured to be the default. Copyright: VyOS maintainers and contributors -.. _update_vyos: -Update VyOS -=========== - -New system images can be added using the :opcmd:`add system image` -command. The command will extract the chosen image and will prompt you -to use the current system configuration and SSH security keys, allowing -for the new image to boot using the current configuration. - -.. note:: Only LTS releases are PGP-signed. - -.. opcmd:: add system image [vrf name] [username user [password pass]] - - Use this command to install a new system image. You can reach the - image from the web (http://, https://) or from your local system, - e.g. /tmp/vyos-1.2.3-amd64.iso. - - The `add system image` command also supports installing new versions - of VyOS through an optional given VRF. Also if URL in question requires - authentication, you can specify an optional username and password via - the commandline which will be passed as "Basic-Auth" to the server. - -If there is not enough **free disk space available**, the installation -will be canceled. To delete images use the :opcmd:`delete system image` -command. - -VyOS configuration is associated to each image, and **each image has a -unique copy of its configuration**. This is different than a traditional -network router where the configuration is shared across all images. - -.. note:: If you have any personal files, like some scripts you created, - and you don't want them to be lost during the upgrade, make sure - those files are stored in ``/config`` as this directory is always copied - to newer installed images. - -You can access files from a previous installation and copy them to your -current image if they were located in the ``/config`` directory. This -can be done using the :opcmd:`copy` command. So, for instance, in order -to copy ``/config/config.boot`` from VyOS 1.2.1 image, you would use the -following command: - -.. code:: - - copy file 1.2.1://config/config.boot to /tmp/config.boot.1.2.1 - - -Example -""""""" - -.. code-block:: none - - vyos@vyos:~$ add system image https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso - Trying to fetch ISO file from https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed - 100 338M 100 338M 0 0 3837k 0 0:01:30 0:01:30 --:--:-- 3929k - ISO download succeeded. - Checking for digital signature file... - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed - 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 - curl: (22) The requested URL returned error: 404 Not Found - - Unable to fetch digital signature file. - Do you want to continue without signature check? (yes/no) [yes] - Checking MD5 checksums of files on the ISO image...OK. - Done! - - What would you like to name this image? [vyos-1.3-rolling-201912201452]: - - OK. This image will be named: vyos-1.3-rolling-201912201452 - - -.. hint:: | The most up-do-date Rolling Release for AMD64 can be accessed using the following URL: - | https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso - -After reboot you might want to verify the version you are running with -the :opcmd:`show version` command. System rollback diff --git a/docs/installation/index.rst b/docs/installation/index.rst index af265121..e5a2a6fd 100644 --- a/docs/installation/index.rst +++ b/docs/installation/index.rst @@ -12,7 +12,8 @@ Installation and Image Management iso virtual/index cloud/index + vyos-on-baremetal update image migrate-from-vyatta - ../vyos-on-baremetal \ No newline at end of file + \ No newline at end of file diff --git a/docs/installation/iso.rst b/docs/installation/iso.rst new file mode 100644 index 00000000..f48ad91c --- /dev/null +++ b/docs/installation/iso.rst @@ -0,0 +1,2 @@ +iso +### \ No newline at end of file diff --git a/docs/appendix/migrate-from-vyatta.rst b/docs/installation/migrate-from-vyatta.rst similarity index 100% rename from docs/appendix/migrate-from-vyatta.rst rename to docs/installation/migrate-from-vyatta.rst diff --git a/docs/installation/upate.rst b/docs/installation/upate.rst new file mode 100644 index 00000000..a3a887f0 --- /dev/null +++ b/docs/installation/upate.rst @@ -0,0 +1,79 @@ +.. _update_vyos: + +Update VyOS +=========== + +New system images can be added using the :opcmd:`add system image` +command. The command will extract the chosen image and will prompt you +to use the current system configuration and SSH security keys, allowing +for the new image to boot using the current configuration. + +.. note:: Only LTS releases are PGP-signed. + +.. opcmd:: add system image [vrf name] [username user [password pass]] + + Use this command to install a new system image. You can reach the + image from the web (http://, https://) or from your local system, + e.g. /tmp/vyos-1.2.3-amd64.iso. + + The `add system image` command also supports installing new versions + of VyOS through an optional given VRF. Also if URL in question requires + authentication, you can specify an optional username and password via + the commandline which will be passed as "Basic-Auth" to the server. + +If there is not enough **free disk space available**, the installation +will be canceled. To delete images use the :opcmd:`delete system image` +command. + +VyOS configuration is associated to each image, and **each image has a +unique copy of its configuration**. This is different than a traditional +network router where the configuration is shared across all images. + +.. note:: If you have any personal files, like some scripts you created, + and you don't want them to be lost during the upgrade, make sure + those files are stored in ``/config`` as this directory is always copied + to newer installed images. + +You can access files from a previous installation and copy them to your +current image if they were located in the ``/config`` directory. This +can be done using the :opcmd:`copy` command. So, for instance, in order +to copy ``/config/config.boot`` from VyOS 1.2.1 image, you would use the +following command: + +.. code:: + + copy file 1.2.1://config/config.boot to /tmp/config.boot.1.2.1 + + +Example +""""""" + +.. code-block:: none + + vyos@vyos:~$ add system image https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso + Trying to fetch ISO file from https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 338M 100 338M 0 0 3837k 0 0:01:30 0:01:30 --:--:-- 3929k + ISO download succeeded. + Checking for digital signature file... + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 + curl: (22) The requested URL returned error: 404 Not Found + + Unable to fetch digital signature file. + Do you want to continue without signature check? (yes/no) [yes] + Checking MD5 checksums of files on the ISO image...OK. + Done! + + What would you like to name this image? [vyos-1.3-rolling-201912201452]: + + OK. This image will be named: vyos-1.3-rolling-201912201452 + + +.. hint:: | The most up-do-date Rolling Release for AMD64 can be accessed using the following URL: + | https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso + +After reboot you might want to verify the version you are running with +the :opcmd:`show version` command. \ No newline at end of file diff --git a/docs/installation/virtual/eve-ng.rst b/docs/installation/virtual/eve-ng.rst new file mode 100644 index 00000000..d5134838 --- /dev/null +++ b/docs/installation/virtual/eve-ng.rst @@ -0,0 +1,8 @@ +###### +EVE-NG +###### + +References +========== + +https://www.eve-ng.net/ \ No newline at end of file diff --git a/docs/appendix/virtual/vyos-on-gns3.rst b/docs/installation/virtual/gns3.rst similarity index 100% rename from docs/appendix/virtual/vyos-on-gns3.rst rename to docs/installation/virtual/gns3.rst diff --git a/docs/installation/virtual/index.rst b/docs/installation/virtual/index.rst new file mode 100644 index 00000000..808439c7 --- /dev/null +++ b/docs/installation/virtual/index.rst @@ -0,0 +1,12 @@ +#################################### +Running VyOS in Virtual Environments +#################################### + +.. toctree:: + :caption: Content + + libvirt + proxmox + vmware + gns3 + eve-ng \ No newline at end of file diff --git a/docs/appendix/virtual/libvirt.rst b/docs/installation/virtual/libvirt.rst similarity index 100% rename from docs/appendix/virtual/libvirt.rst rename to docs/installation/virtual/libvirt.rst diff --git a/docs/installation/virtual/proxmox.rst b/docs/installation/virtual/proxmox.rst new file mode 100644 index 00000000..3ee9d70a --- /dev/null +++ b/docs/installation/virtual/proxmox.rst @@ -0,0 +1,8 @@ +####### +Proxmox +####### + +References +========== + +https://www.proxmox.com/en/proxmox-ve \ No newline at end of file diff --git a/docs/appendix/virtual/vyos-on-vmware.rst b/docs/installation/virtual/vmware.rst similarity index 100% rename from docs/appendix/virtual/vyos-on-vmware.rst rename to docs/installation/virtual/vmware.rst diff --git a/docs/appendix/vyos-on-baremetal.rst b/docs/installation/vyos-on-baremetal.rst similarity index 100% rename from docs/appendix/vyos-on-baremetal.rst rename to docs/installation/vyos-on-baremetal.rst From a3f7e4ae450248bb5b28474d908e51e6560cb68d Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 19:36:16 +0100 Subject: [PATCH 14/28] arange http-api and command-scripting --- docs/appendix/release-notes.rst | 305 ------------------ .../command-scripting.rst | 0 docs/{appendix => automation}/http-api.rst | 0 docs/automation/index.rst | 9 +- 4 files changed, 8 insertions(+), 306 deletions(-) delete mode 100644 docs/appendix/release-notes.rst rename docs/{appendix => automation}/command-scripting.rst (100%) rename docs/{appendix => automation}/http-api.rst (100%) diff --git a/docs/appendix/release-notes.rst b/docs/appendix/release-notes.rst deleted file mode 100644 index 89454fa0..00000000 --- a/docs/appendix/release-notes.rst +++ /dev/null @@ -1,305 +0,0 @@ -.. _release-notes: - -############# -Release Notes -############# - -1.2 (Crux) -========== - -1.2.5 ------ - -1.2.5 is a maintenance release made in April 2020. - -Resolved issues -^^^^^^^^^^^^^^^ - -* :vytask:`1020` OSPF Stops distributing default route after a while -* :vytask:`1228` pppoe default-route force option not working (Rel 1.2.0-rc11) -* :vytask:`1301` bgp peer-groups don't work when "no-ipv4-unicast" is enabled. -* :vytask:`1341` Adding rate-limiter for pppoe server users -* :vytask:`1376` Incorrect DHCP lease counting -* :vytask:`1392` Large firewall rulesets cause the system to lose configuration and crash at startup -* :vytask:`1416` 2 dhcp server run in failover mode can't sync hostname with each other -* :vytask:`1452` accel-pppoe - add vendor option to shaper -* :vytask:`1490` BGP configuration (is lost|not applied) when updating 1.1.8 -> 1.2.1 -* :vytask:`1780` Adding ipsec ike closeaction -* :vytask:`1803` Unbind NTP while it's not requested... -* :vytask:`1821` "authentication mode radius" has no effect for PPPoE server -* :vytask:`1827` Increase default gc_thresh -* :vytask:`1828` Missing completion helper for "set system syslog host 192.0.2.1 facility all protocol" -* :vytask:`1832` radvd adding feature DNSSL branch.example.com example.com to existing package -* :vytask:`1837` PPPoE unrecognized option 'replacedefaultroute' -* :vytask:`1851` wireguard - changing the pubkey on an existing peer seems to destroy the running config. -* :vytask:`1858` l2tp: Delete depricated outside-nexthop and add gateway-address -* :vytask:`1864` Lower IPSec DPD timeout lower limit from 10s -> 2s -* :vytask:`1879` Extend Dynamic DNS XML definition value help strings and validators -* :vytask:`1881` Execute permissions are removed from custom SNMP scripts at commit time -* :vytask:`1884` Keeping VRRP transition-script native behaviour and adding stop-script -* :vytask:`1891` Router announcements broken on boot -* :vytask:`1900` Enable SNMP for VRRP. -* :vytask:`1902` Add redistribute non main table in bgp -* :vytask:`1909` Incorrect behaviour of static routes with overlapping networks -* :vytask:`1913` "system ipv6 blacklist" command has no effect -* :vytask:`1914` IPv6 multipath hash policy does not apply -* :vytask:`1917` Update WireGuard to Debian release 0.0.20191219-1 -* :vytask:`1934` Change default hostname when deploy from OVA without params. -* :vytask:`1935` NIC identification and usage problem in Hyper-V environments -* :vytask:`1936` pppoe-server CLI control features -* :vytask:`1964` SNMP Script-extensions allows names with spaces, but commit fails -* :vytask:`1967` BGP parameter "enforce-first-as" does not work anymore -* :vytask:`1970` Correct adding interfaces on boot -* :vytask:`1971` Missing modules in initrd.img for PXE boot -* :vytask:`1998` Update FRR to 7.3 -* :vytask:`2001` Error when router reboot -* :vytask:`2032` Monitor bandwidth bits -* :vytask:`2059` Set source-validation on bond vif don't work -* :vytask:`2066` PPPoE interface can be created multiple times - last wins -* :vytask:`2069` PPPoE-client does not works with service-name option -* :vytask:`2077` ISO build from crux branch is failing -* :vytask:`2079` Update Linux Kernel to v4.19.106 -* :vytask:`2087` Add maxfail 0 option to pppoe configuration. -* :vytask:`2100` BGP route adverisement wih checks rib -* :vytask:`2120` "reset vpn ipsec-peer" doesn't work with named peers -* :vytask:`2197` Cant add vif-s interface into a bridge -* :vytask:`2228` WireGuard does not allow ports < 1024 to be used -* :vytask:`2252` HTTP API add system image can return '504 Gateway Time-out' -* :vytask:`2272` Set system flow-accounting disable-imt has syntax error -* :vytask:`2276` PPPoE server vulnerability - - -1.2.4 ------ - -1.2.4 is a maintenance release made in December 2019. - -Resolved issues -^^^^^^^^^^^^^^^ - -* :vytask:`T258` Can not configure wan load-balancing on vyos-1.2 -* :vytask:`T818` SNMP v3 - remove required engineid from user node -* :vytask:`T1030` Upgrade ddclient from 3.8.2 to 3.9.0 (support Cloudflare API v4) -* :vytask:`T1183` BFD Support via FRR -* :vytask:`T1299` Allow SNMPd to be extended with custom scripts -* :vytask:`T1351` accel-pppoe adding CIDR based IP pool option -* :vytask:`T1391` In route-map set community additive -* :vytask:`T1394` syslog systemd and host_name.py race condition -* :vytask:`T1401` Copying files with the FTP protocol fails if the password contains special characters -* :vytask:`T1421` OpenVPN client push-route stopped working, needs added quotes to fix -* :vytask:`T1430` Add options for custom DHCP client-id and hostname -* :vytask:`T1447` Python subprocess called without import in host_name.py -* :vytask:`T1470` improve output of "show dhcpv6 server leases" -* :vytask:`T1485` Enable 'AdvIntervalOpt' option in for radvd.conf -* :vytask:`T1496` Separate rolling release and LTS kernel builds -* :vytask:`T1560` "set load-balancing wan rule 0" causes segfault and prevents load balancing from starting -* :vytask:`T1568` strip-private command improvement for additional masking of IPv6 and MAC address -* :vytask:`T1578` completion offers "show table", but show table does not exist -* :vytask:`T1593` Support ip6gre -* :vytask:`T1597` /usr/sbin/rsyslogd after deleting "system syslog" -* :vytask:`T1638` vyos-hostsd not setting system domain name -* :vytask:`T1678` hostfile-update missing line feed -* :vytask:`T1694` NTPd: Do not listen on all interfaces by default -* :vytask:`T1701` Delete domain-name and domain-search won't work -* :vytask:`T1705` High CPU usage by bgpd when snmp is active -* :vytask:`T1707` DHCP static mapping and exclude address not working -* :vytask:`T1708` Update Rolling Release Kernel to 4.19.76 -* :vytask:`T1709` Update WireGuard to 0.0.20190913 -* :vytask:`T1716` Update Intel NIC drivers to recent versions -* :vytask:`T1726` Update Linux Firmware binaries to a more recent version 2019-03-14 -> 2019-10-07 -* :vytask:`T1728` Update Linux Kernel to 4.19.79 -* :vytask:`T1737` SNMP tab completion missing -* :vytask:`T1738` Copy SNMP configuration from node to node raises exception -* :vytask:`T1740` Broken OSPFv2 virtual-link authentication -* :vytask:`T1742` NHRP unable to commit. -* :vytask:`T1745` dhcp-server commit fails with "DHCP range stop address x must be greater or equal to the range start address y!" when static mapping has same IP as range stop -* :vytask:`T1749` numeric validator doesn't support multiple ranges -* :vytask:`T1769` Remove complex SNMPv3 Transport Security Model (TSM) -* :vytask:`T1772` constraints in XML are partially broken -* :vytask:`T1778` Kilobits/Megabits difference in configuration Vyos/FRR -* :vytask:`T1780` Adding ipsec ike closeaction -* :vytask:`T1786` disable-dhcp-nameservers is missed in current host_name.py implementation -* :vytask:`T1788` Intel QAT (QuickAssist Technology ) implementation -* :vytask:`T1792` Update WireGuard to Debian release 0.0.20191012-1 -* :vytask:`T1800` Update Linux Kernel to v4.19.84 -* :vytask:`T1809` Wireless: SSID scan does not work in AP mode -* :vytask:`T1811` Upgrade from 1.1.8: Config file migration failed: module=l2tp -* :vytask:`T1812` DHCP: hostnames of clients not resolving after update v1.2.3 -> 1.2-rolling -* :vytask:`T1819` Reboot kills SNMPv3 configuration -* :vytask:`T1822` Priority inversion wireless interface dhcpv6 -* :vytask:`T1825` Improve DHCP configuration error message -* :vytask:`T1836` import-conf-mode-commands in vyos-1x/scripts fails to create an xml -* :vytask:`T1839` LLDP shows "VyOS unknown" instead of "VyOS" -* :vytask:`T1841` PPP ipv6-up.d direcotry missing -* :vytask:`T1893` igmp-proxy: Do not allow adding unknown interface -* :vytask:`T1903` Implementation udev predefined interface naming -* :vytask:`T1904` update eth1 and eth2 link files for the vep4600 - - -1.2.3 ------ - -1.2.3 is a maintenance and feature backport release made in September 2019. - -New features -^^^^^^^^^^^^ - -* HTTP API -* :vytask:`T1524` "set service dns forwarding allow-from " - option for limiting queries to specific client networks -* :vytask:`T1503` Functions for checking if a commit is in progress -* :vytask:`T1543` "set system contig-mangement commit-archive source-address" - option -* :vytask:`T1554` Intel NIC drivers now support receive side scaling and - multiqueue - -Resolved issues -^^^^^^^^^^^^^^^ - -* :vytask:`T1209` OSPF max-metric values over 100 no longer causes commit - errors -* :vytask:`T1333` Fixes issue with DNS forwarding not performing recursive - lookups on domain specific forwarders -* :vytask:`T1362` Special characters in VRRP passwords are handled correctly -* :vytask:`T1377` BGP weight is applied properly -* :vytask:`T1420` Fixed permission for log files -* :vytask:`T1425` Wireguard interfaces now support /31 addresses -* :vytask:`T1428` Wireguard correctly handles firewall marks -* :vytask:`T1439` DHCPv6 static mappings now work correctly -* :vytask:`T1450` Flood ping commands now works correctly -* :vytask:`T1460` Op mode "show firewall" commands now support counters longer - than 8 digits (T1460) -* :vytask:`T1465` Fixed priority inversion in VTI commands -* :vytask:`T1468` Fixed remote-as check in the BGP route-reflector-client option -* :vytask:`T1472` It's now possible to re-create VRRP groups with RFC - compatibility mode enabled -* :vytask:`T1527` Fixed a typo in DHCPv6 server help strings -* :vytask:`T1529` Unnumbered BGP peers now support VLAN interfaces -* :vytask:`T1530` Fixed "set system syslog global archive file" command -* :vytask:`T1531` Multiple fixes in cluster configuration scripts -* :vytask:`T1537` Fixed missing help text for "service dns" -* :vytask:`T1541` Fixed input validation in DHCPv6 relay options -* :vytask:`T1551` It's now possible to create a QinQ interface and a firewall - assigned to it in one commit -* :vytask:`T1559` URL filtering now uses correct rule database path and works - again -* :vytask:`T1579` "show log vpn ipsec" command works again -* :vytask:`T1576` "show arp interface " command works again -* :vytask:`T1605` Fixed regression in L2TP/IPsec server -* :vytask:`T1613` Netflow/sFlow captures IPv6 traffic correctly -* :vytask:`T1616` "renew dhcpv6" command now works from op mode -* :vytask:`T1642` BGP remove-private-as option iBGP vs eBGP check works - correctly now -* :vytask:`T1540`, :vytask:`T1360`, :vytask:`T1264`, :vytask:`T1623` Multiple - improvements in name servers and hosts configuration handling - -Internals -^^^^^^^^^ - -``/etc/resolv.conf`` and ``/etc/hosts`` files are now managed by the -*vyos-hostsd* service that listens on a ZMQ socket for update messages. - -1.2.2 ------ - -1.2.2 is a maintenance release made in July 2019. - -New features -^^^^^^^^^^^^ - -* Options for per-interface MSS clamping. -* BGP extended next-hop capability -* Relaxed BGP multipath option -* Internal and external options for "remote-as" (accept any AS as long as it's - the same to this router or different, respectively) -* "Unnumbered" (interface-based) BGP peers -* BGP no-prepend option -* Additive BGP community option -* OSPFv3 network type option -* Custom arguments for VRRP scripts -* A script for querying values from config files - -Resolved issues -^^^^^^^^^^^^^^^ - -* Linux kernel 4.19.54, including a fix for the TCP SACK vulnerability -* :vytask:`T1371` VRRP health-check scripts now can use arguments -* :vytask:`T1497` DNS server addresses coming from a DHCP server are now - correctly propagated to resolv.conf -* :vytask:`T1469` Domain-specific name servers in DNS forwarding are now used - for recursive queries -* :vytask:`T1433` ``run show dhcpv6 server leases`` now display leases correctly -* :vytask:`T1461` Deleting ``firewall options`` node no longer causes errors -* :vytask:`T1458` Correct hostname is sent to remote syslog again -* :vytask:`T1438` Board serial number from DMI is correctly displayed in - ``show version`` -* :vytask:`T1358`, :vytask:`T1355`, :vytask:`T1294` Multiple corrections in - remote syslog config -* :vytask:`T1255` Fixed missing newline in ``/etc/hosts`` -* :vytask:`T1174` ``system domain-name`` is correctly included in - ``/etc/resolv.conf`` -* :vytask:`T1465` Fixed priority inversion in ``interfaces vti vtiX ip`` - settings -* :vytask:`T1446` Fixed errors when installing with RAID1 on UEFI machines -* :vytask:`T1387` Fixed an error on disabling an interfaces that has no address -* :vytask:`T1367` Fixed deleting VLAN interface with non-default MTU -* :vytask:`T1505` vyos.config ``return_effective_values()`` function now - correctly returns a list rather than a string - -1.2.1 ------ - -VyOS 1.2.1 is a maintenance release made in April 2019. - -Resolved issues -^^^^^^^^^^^^^^^ - -* Package updates: kernel 4.19.32, open-vm-tools 10.3, latest Intel NIC drivers -* :vytask:`T1326` The kernel now includes drivers for various USB serial - adapters, which allows people to add a serial console to a machine without - onboard RS232, or connect to something else from the router -* The collection of network card firmware is now much more extensive -* :vytask:`T1271` VRRP now correctly uses a virtual rather than physical MAC - addresses in the RFC-compliant mode -* :vytask:`T1330` DHCP WPAD URL option works correctly again -* :vytask:`T1312` Many to many NAT rules now can use source/destination and - translation networks of non-matching size. If 1:1 network bits translation is - desired, it's now users responsibility to check if prefix length matches. -* :vytask:`T1290` IPv6 network prefix translation is fixed -* :vytask:`T1308` Non-alphanumeric characters such as ``>`` can now be safely - used in PPPoE passwords -* :vytask:`T1305` ``show | commands`` no longer fails when a config section ends - with a leaf node such as ``timezone`` in ``show system | commands`` -* :vytask:`T1235` ``show | commands`` correctly works in config mode now -* :vytask:`T1298` VTI is now compatible with the DHCP-interface IPsec option -* :vytask:`T1277` ``show dhcp server statistics`` command was broken in latest - Crux -* :vytask:`T1261` An issue with TFTP server refusing to listen on addresses - other than loopback was fixed -* :vytask:`T1224` Template issue that might cause UDP broadcast relay fail to - start is fixed -* :vytask:`T1067` VXLAN value validation is improved -* :vytask:`T1211` Blank hostnames in DHCP updates no longer can crash DNS - forwarding -* :vytask:`T1322` Correct configuration is now generated for DHCPv6 relays with - more than one upstream interface -* :vytask:`T1234` ``relay-agents-packets`` option works correctly now -* :vytask:`T1231` Dynamic DNS data is now cleaned on configuration change -* :vytask:`T1282` Remote Syslog can now use a fully qualified domain name -* :vytask:`T1279` ACPI power off works again -* :vytask:`T1247` Negation in WAN load balancing rules works again -* :vytask:`T1218` FRR staticd now starts on boot correctly -* :vytask:`T1296` The installer now correctly detects SD card devices -* :vytask:`T1225` Wireguard peers can be disabled now -* :vytask:`T1217` The issue with Wireguard interfaces impossible to delete - is fixed -* :vytask:`T1160` Unintended IPv6 access is fixed in SNMP configuration -* :vytask:`T1060` It's now possible to exclude hosts from the transparent - web proxy -* :vytask:`T484` An issue with rules impossible to delete from the zone-based - firewall is fixed - -Earlier releases -================ - -Release notes for legacy versions (1.1.x, 1.0.x) can be found in the `archived wiki `_. diff --git a/docs/appendix/command-scripting.rst b/docs/automation/command-scripting.rst similarity index 100% rename from docs/appendix/command-scripting.rst rename to docs/automation/command-scripting.rst diff --git a/docs/appendix/http-api.rst b/docs/automation/http-api.rst similarity index 100% rename from docs/appendix/http-api.rst rename to docs/automation/http-api.rst diff --git a/docs/automation/index.rst b/docs/automation/index.rst index a3df9bc0..1f2b40b1 100644 --- a/docs/automation/index.rst +++ b/docs/automation/index.rst @@ -6,4 +6,11 @@ VyOS Automation * Ansible * Saltstack * HTTP-API - * startup scripts \ No newline at end of file + * startup scripts + + +.. toctree:: + :maxdepth: 1 + + command-scripting + http-api \ No newline at end of file From 0abea04850dfdaa0b56fc6dec94e5303300ba712 Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 21:18:33 +0100 Subject: [PATCH 15/28] arrange firewall --- .../firewall/index.rst} | 0 docs/configuration/index.rst | 23 +++++++++++++++++++ docs/index.rst | 1 - 3 files changed, 23 insertions(+), 1 deletion(-) rename docs/{firewall.rst => configuration/firewall/index.rst} (100%) create mode 100644 docs/configuration/index.rst diff --git a/docs/firewall.rst b/docs/configuration/firewall/index.rst similarity index 100% rename from docs/firewall.rst rename to docs/configuration/firewall/index.rst diff --git a/docs/configuration/index.rst b/docs/configuration/index.rst new file mode 100644 index 00000000..bce013cb --- /dev/null +++ b/docs/configuration/index.rst @@ -0,0 +1,23 @@ +################### +Configuration Guide +################### + +The following structure respresent the cli structure. + +.. toctree:: + :maxdepth: 1 + :includehidden: + + firewall/index + highavailability/index + interfaces/index + loadbalancing/index + nat/index + policy/index + protocols/index + service/index + system/index + trafficpolicy/index + vpn/index + vrf/index + zonepolicy/index \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 3322bf8d..4612d5f8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,7 +8,6 @@ VyOS User Guide .. toctree:: :maxdepth: 2 :hidden: - :caption: FIND CAPTION NAME introducing/about introducing/history From bfb3814cd120d1bb661af26b3c55341f1697b397 Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 21:25:50 +0100 Subject: [PATCH 16/28] arrange loadbalancing, high availability, qos --- .../highavailability/index.rst} | 0 .../loadbalancing/index.rst} | 0 docs/{qos.rst => configuration/trafficpolicy/index.rst} | 5 +++++ 3 files changed, 5 insertions(+) rename docs/{high-availability.rst => configuration/highavailability/index.rst} (100%) rename docs/{load-balancing.rst => configuration/loadbalancing/index.rst} (100%) rename docs/{qos.rst => configuration/trafficpolicy/index.rst} (99%) diff --git a/docs/high-availability.rst b/docs/configuration/highavailability/index.rst similarity index 100% rename from docs/high-availability.rst rename to docs/configuration/highavailability/index.rst diff --git a/docs/load-balancing.rst b/docs/configuration/loadbalancing/index.rst similarity index 100% rename from docs/load-balancing.rst rename to docs/configuration/loadbalancing/index.rst diff --git a/docs/qos.rst b/docs/configuration/trafficpolicy/index.rst similarity index 99% rename from docs/qos.rst rename to docs/configuration/trafficpolicy/index.rst index 6826b83c..babccd6f 100644 --- a/docs/qos.rst +++ b/docs/configuration/trafficpolicy/index.rst @@ -1,5 +1,10 @@ .. _qos: +############## +Traffic Policy +############## + + *** QoS *** From e7f01e6efc8578603592ff86c031d46f1f1f9d82 Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 21:32:45 +0100 Subject: [PATCH 17/28] arrange: nat, PBR, policy --- docs/{nat.rst => configuration/nat/index.rst} | 6 ++ docs/{ => configuration/nat}/nptv6.rst | 0 .../policy/index.rst} | 68 +++++++++++++++++++ docs/routing/policy.rst | 65 ------------------ 4 files changed, 74 insertions(+), 65 deletions(-) rename docs/{nat.rst => configuration/nat/index.rst} (99%) rename docs/{ => configuration/nat}/nptv6.rst (100%) rename docs/{routing/pbr.rst => configuration/policy/index.rst} (67%) delete mode 100644 docs/routing/policy.rst diff --git a/docs/nat.rst b/docs/configuration/nat/index.rst similarity index 99% rename from docs/nat.rst rename to docs/configuration/nat/index.rst index 17698c26..85bd41d5 100644 --- a/docs/nat.rst +++ b/docs/configuration/nat/index.rst @@ -4,6 +4,12 @@ NAT ### +.. toctree:: + :maxdepth: 1 + :includehidden: + + nptv6 + :abbr:`NAT (Network Address Translation)` is a common method of remapping one IP address space into another by modifying network address information in the IP header of packets while they are in transit across diff --git a/docs/nptv6.rst b/docs/configuration/nat/nptv6.rst similarity index 100% rename from docs/nptv6.rst rename to docs/configuration/nat/nptv6.rst diff --git a/docs/routing/pbr.rst b/docs/configuration/policy/index.rst similarity index 67% rename from docs/routing/pbr.rst rename to docs/configuration/policy/index.rst index 7b0341cb..4be494e5 100644 --- a/docs/routing/pbr.rst +++ b/docs/configuration/policy/index.rst @@ -1,5 +1,72 @@ .. include:: ../_include/need_improvement.txt +###### +Policy +###### + +Routing Policies could be used to tell the router (self or neighbors) what +routes and their attributes needs to be put into the routing table. + +There could be a wide range of routing policies. Some examples are below: + +* Set some metric to routes learned from a particular neighbor +* Set some attributes (like AS PATH or Community value) to advertised routes to neighbors +* Prefer a specific routing protocol routes over another routing protocol running on the same router + +Example +======= + +**Policy definition:** + +.. code-block:: none + + # Create policy + set policy route-map setmet rule 2 action 'permit' + set policy route-map setmet rule 2 set as-path-prepend '2 2 2' + + # Apply policy to BGP + set protocols bgp 1 neighbor 203.0.113.2 address-family ipv4-unicast route-map import 'setmet' + set protocols bgp 1 neighbor 203.0.113.2 address-family ipv4-unicast soft-reconfiguration 'inbound' + +Using 'soft-reconfiguration' we get the policy update without bouncing the +neighbor. + +**Routes learned before routing policy applied:** + +.. code-block:: none + + vyos@vos1:~$ show ip bgp + BGP table version is 0, local router ID is 192.168.56.101 + Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, + r RIB-failure, S Stale, R Removed + Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path + *> 198.51.100.3/32 203.0.113.2 1 0 2 i < Path + + Total number of prefixes 1 + +**Routes learned after routing policy applied:** + +.. code-block:: none + + vyos@vos1:~$ sho ip b + BGP table version is 0, local router ID is 192.168.56.101 + Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, + r RIB-failure, S Stale, R Removed + Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path + *> 198.51.100.3/32 203.0.113.2 1 0 2 2 2 2 i + + Total number of prefixes 1 + vyos@vos1:~$ + +You now see the longer AS path. + + +.. include:: ../_include/need_improvement.txt + .. _routing-pbr: ### @@ -135,3 +202,4 @@ Add multiple source IP in one rule with same priority set policy local-route rule 101 source '192.0.1.254' set policy local-route rule 101 source '192.0.1.253' set policy local-route rule 101 source '203.0.113.0/24' + diff --git a/docs/routing/policy.rst b/docs/routing/policy.rst deleted file mode 100644 index 4eeb40d6..00000000 --- a/docs/routing/policy.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. include:: ../_include/need_improvement.txt - -###### -Policy -###### - -Routing Policies could be used to tell the router (self or neighbors) what -routes and their attributes needs to be put into the routing table. - -There could be a wide range of routing policies. Some examples are below: - -* Set some metric to routes learned from a particular neighbor -* Set some attributes (like AS PATH or Community value) to advertised routes to neighbors -* Prefer a specific routing protocol routes over another routing protocol running on the same router - -Example -======= - -**Policy definition:** - -.. code-block:: none - - # Create policy - set policy route-map setmet rule 2 action 'permit' - set policy route-map setmet rule 2 set as-path-prepend '2 2 2' - - # Apply policy to BGP - set protocols bgp 1 neighbor 203.0.113.2 address-family ipv4-unicast route-map import 'setmet' - set protocols bgp 1 neighbor 203.0.113.2 address-family ipv4-unicast soft-reconfiguration 'inbound' - -Using 'soft-reconfiguration' we get the policy update without bouncing the -neighbor. - -**Routes learned before routing policy applied:** - -.. code-block:: none - - vyos@vos1:~$ show ip bgp - BGP table version is 0, local router ID is 192.168.56.101 - Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, - r RIB-failure, S Stale, R Removed - Origin codes: i - IGP, e - EGP, ? - incomplete - - Network Next Hop Metric LocPrf Weight Path - *> 198.51.100.3/32 203.0.113.2 1 0 2 i < Path - - Total number of prefixes 1 - -**Routes learned after routing policy applied:** - -.. code-block:: none - - vyos@vos1:~$ sho ip b - BGP table version is 0, local router ID is 192.168.56.101 - Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, - r RIB-failure, S Stale, R Removed - Origin codes: i - IGP, e - EGP, ? - incomplete - - Network Next Hop Metric LocPrf Weight Path - *> 198.51.100.3/32 203.0.113.2 1 0 2 2 2 2 i - - Total number of prefixes 1 - vyos@vos1:~$ - -You now see the longer AS path. From 4abded8025a47990e58cd0a5fe9b96e38f4a3715 Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 21:52:28 +0100 Subject: [PATCH 18/28] arrange: interfaces --- Pipfile | 16 +++++++++++ .../interfaces/bonding.rst} | 0 .../{ => configuration}/interfaces/bridge.rst | 0 docs/{ => configuration}/interfaces/dummy.rst | 0 .../interfaces/ethernet.rst | 0 .../{ => configuration}/interfaces/geneve.rst | 0 docs/configuration/interfaces/index.rst | 28 +++++++++++++++++++ .../{ => configuration}/interfaces/l2tpv3.rst | 0 .../interfaces/loopback.rst | 0 .../{ => configuration}/interfaces/macsec.rst | 0 .../interfaces}/openvpn.rst | 0 docs/{ => configuration}/interfaces/pppoe.rst | 0 .../interfaces/pseudo-ethernet.rst | 0 .../{ => configuration}/interfaces/tunnel.rst | 19 ------------- docs/configuration/interfaces/vti.rst | 22 +++++++++++++++ docs/{ => configuration}/interfaces/vxlan.rst | 0 .../interfaces}/wireguard.rst | 0 .../interfaces/wireless.rst | 0 .../interfaces/wirelessmodem.rst | 0 19 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 Pipfile rename docs/{interfaces/bond.rst => configuration/interfaces/bonding.rst} (100%) rename docs/{ => configuration}/interfaces/bridge.rst (100%) rename docs/{ => configuration}/interfaces/dummy.rst (100%) rename docs/{ => configuration}/interfaces/ethernet.rst (100%) rename docs/{ => configuration}/interfaces/geneve.rst (100%) create mode 100644 docs/configuration/interfaces/index.rst rename docs/{ => configuration}/interfaces/l2tpv3.rst (100%) rename docs/{ => configuration}/interfaces/loopback.rst (100%) rename docs/{ => configuration}/interfaces/macsec.rst (100%) rename docs/{vpn => configuration/interfaces}/openvpn.rst (100%) rename docs/{ => configuration}/interfaces/pppoe.rst (100%) rename docs/{ => configuration}/interfaces/pseudo-ethernet.rst (100%) rename docs/{ => configuration}/interfaces/tunnel.rst (95%) create mode 100644 docs/configuration/interfaces/vti.rst rename docs/{ => configuration}/interfaces/vxlan.rst (100%) rename docs/{vpn => configuration/interfaces}/wireguard.rst (100%) rename docs/{ => configuration}/interfaces/wireless.rst (100%) rename docs/{ => configuration}/interfaces/wirelessmodem.rst (100%) diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..423092c4 --- /dev/null +++ b/Pipfile @@ -0,0 +1,16 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +sphinx-rtd-theme = "*" +docutils = "*" +lxml = "*" +sphinx-notfound-page = "*" +Sphinx = ">=1.4.3" + +[dev-packages] + +[requires] +python_version = "3.9" diff --git a/docs/interfaces/bond.rst b/docs/configuration/interfaces/bonding.rst similarity index 100% rename from docs/interfaces/bond.rst rename to docs/configuration/interfaces/bonding.rst diff --git a/docs/interfaces/bridge.rst b/docs/configuration/interfaces/bridge.rst similarity index 100% rename from docs/interfaces/bridge.rst rename to docs/configuration/interfaces/bridge.rst diff --git a/docs/interfaces/dummy.rst b/docs/configuration/interfaces/dummy.rst similarity index 100% rename from docs/interfaces/dummy.rst rename to docs/configuration/interfaces/dummy.rst diff --git a/docs/interfaces/ethernet.rst b/docs/configuration/interfaces/ethernet.rst similarity index 100% rename from docs/interfaces/ethernet.rst rename to docs/configuration/interfaces/ethernet.rst diff --git a/docs/interfaces/geneve.rst b/docs/configuration/interfaces/geneve.rst similarity index 100% rename from docs/interfaces/geneve.rst rename to docs/configuration/interfaces/geneve.rst diff --git a/docs/configuration/interfaces/index.rst b/docs/configuration/interfaces/index.rst new file mode 100644 index 00000000..85d2c177 --- /dev/null +++ b/docs/configuration/interfaces/index.rst @@ -0,0 +1,28 @@ +########## +Interfaces +########## + + +.. toctree:: + :maxdepth: 1 + :includehidden: + + bonding + bridge + dummy + ethernet + geneve + l2tpv3 + loopback + macsec + openvpn + pppoe + pseudo-ethernet + tunnel + vti + vxlan + wireguard + wireless + wirelessmodem + + diff --git a/docs/interfaces/l2tpv3.rst b/docs/configuration/interfaces/l2tpv3.rst similarity index 100% rename from docs/interfaces/l2tpv3.rst rename to docs/configuration/interfaces/l2tpv3.rst diff --git a/docs/interfaces/loopback.rst b/docs/configuration/interfaces/loopback.rst similarity index 100% rename from docs/interfaces/loopback.rst rename to docs/configuration/interfaces/loopback.rst diff --git a/docs/interfaces/macsec.rst b/docs/configuration/interfaces/macsec.rst similarity index 100% rename from docs/interfaces/macsec.rst rename to docs/configuration/interfaces/macsec.rst diff --git a/docs/vpn/openvpn.rst b/docs/configuration/interfaces/openvpn.rst similarity index 100% rename from docs/vpn/openvpn.rst rename to docs/configuration/interfaces/openvpn.rst diff --git a/docs/interfaces/pppoe.rst b/docs/configuration/interfaces/pppoe.rst similarity index 100% rename from docs/interfaces/pppoe.rst rename to docs/configuration/interfaces/pppoe.rst diff --git a/docs/interfaces/pseudo-ethernet.rst b/docs/configuration/interfaces/pseudo-ethernet.rst similarity index 100% rename from docs/interfaces/pseudo-ethernet.rst rename to docs/configuration/interfaces/pseudo-ethernet.rst diff --git a/docs/interfaces/tunnel.rst b/docs/configuration/interfaces/tunnel.rst similarity index 95% rename from docs/interfaces/tunnel.rst rename to docs/configuration/interfaces/tunnel.rst index c14314d1..4b9da26b 100644 --- a/docs/interfaces/tunnel.rst +++ b/docs/configuration/interfaces/tunnel.rst @@ -210,26 +210,7 @@ that are discarding IP protocol 47 or blocking your source/desintation traffic. 4 packets transmitted, 4 received, 0% packet loss, time 3008ms rtt min/avg/max/mdev = 1.055/1.729/1.989/0.395 ms -Virtual Tunnel Interface (VTI) ------------------------------- -Set Virtual Tunnel Interface - -.. code-block:: none - - set interfaces vti vti0 address 192.168.2.249/30 - set interfaces vti vti0 address 2001:db8:2::249/64 - -Results in: - -.. code-block:: none - - vyos@vyos# show interfaces vti - vti vti0 { - address 192.168.2.249/30 - address 2001:db8:2::249/64 - description "Description" - } .. _`other proposals`: https://www.isc.org/othersoftware/ .. _`Hurricane Electric`: https://tunnelbroker.net/ diff --git a/docs/configuration/interfaces/vti.rst b/docs/configuration/interfaces/vti.rst new file mode 100644 index 00000000..62cd13f3 --- /dev/null +++ b/docs/configuration/interfaces/vti.rst @@ -0,0 +1,22 @@ +############################## +Virtual Tunnel Interface (VTI) +############################## + + +Set Virtual Tunnel Interface + +.. code-block:: none + + set interfaces vti vti0 address 192.168.2.249/30 + set interfaces vti vti0 address 2001:db8:2::249/64 + +Results in: + +.. code-block:: none + + vyos@vyos# show interfaces vti + vti vti0 { + address 192.168.2.249/30 + address 2001:db8:2::249/64 + description "Description" + } \ No newline at end of file diff --git a/docs/interfaces/vxlan.rst b/docs/configuration/interfaces/vxlan.rst similarity index 100% rename from docs/interfaces/vxlan.rst rename to docs/configuration/interfaces/vxlan.rst diff --git a/docs/vpn/wireguard.rst b/docs/configuration/interfaces/wireguard.rst similarity index 100% rename from docs/vpn/wireguard.rst rename to docs/configuration/interfaces/wireguard.rst diff --git a/docs/interfaces/wireless.rst b/docs/configuration/interfaces/wireless.rst similarity index 100% rename from docs/interfaces/wireless.rst rename to docs/configuration/interfaces/wireless.rst diff --git a/docs/interfaces/wirelessmodem.rst b/docs/configuration/interfaces/wirelessmodem.rst similarity index 100% rename from docs/interfaces/wirelessmodem.rst rename to docs/configuration/interfaces/wirelessmodem.rst From ad0dc9cf1a2161cb0bf2cfbc9c6fd4df2f78ab3a Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 29 Nov 2020 22:00:20 +0100 Subject: [PATCH 19/28] cmdinclude: fix errormsg --- docs/_ext/vyos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_ext/vyos.py b/docs/_ext/vyos.py index 4b4b1a89..89cc8ab7 100644 --- a/docs/_ext/vyos.py +++ b/docs/_ext/vyos.py @@ -219,9 +219,9 @@ class CfgInclude(Directive): 'Cannot encode input file path "%s" ' '(wrong locale?).' % (self.name, SafeString(path))) - except IOError: + except IOError as error: raise self.severe(u'Problems with "%s" directive path:\n%s.' % - (self.name, ErrorString(error))) + (self.name, error)) startline = self.options.get('start-line', None) endline = self.options.get('end-line', None) try: From e33e1268f944be445b5a771df0e97e913487512f Mon Sep 17 00:00:00 2001 From: rebortg Date: Mon, 30 Nov 2020 19:46:59 +0100 Subject: [PATCH 20/28] change include to absolute path --- docs/_ext/vyos.py | 9 +++++-- docs/_include/interface-common-with-dhcp.txt | 8 +++--- .../interface-common-without-dhcp.txt | 4 +-- docs/_include/interface-common.txt | 18 ++++++------- docs/_include/interface-dhcpv6-options.txt | 2 +- docs/_include/interface-vlan-8021ad.txt | 26 +++++++++---------- docs/_include/interface-vlan-8021q.txt | 24 ++++++++--------- docs/configuration/firewall/index.rst | 1 + docs/configuration/interfaces/bonding.rst | 4 +-- docs/configuration/interfaces/bridge.rst | 4 +-- docs/configuration/interfaces/dummy.rst | 8 +++--- docs/configuration/interfaces/ethernet.rst | 6 ++--- docs/configuration/interfaces/geneve.rst | 2 +- docs/configuration/interfaces/l2tpv3.rst | 4 +-- docs/configuration/interfaces/loopback.rst | 4 +-- docs/configuration/interfaces/macsec.rst | 2 +- docs/configuration/interfaces/openvpn.rst | 2 +- docs/configuration/interfaces/pppoe.rst | 8 +++--- .../interfaces/pseudo-ethernet.rst | 4 +-- docs/configuration/interfaces/tunnel.rst | 2 +- docs/configuration/interfaces/vxlan.rst | 2 +- docs/configuration/interfaces/wireless.rst | 6 ++--- .../interfaces/wirelessmodem.rst | 6 ++--- docs/configuration/nat/nptv6.rst | 2 +- docs/configuration/policy/index.rst | 4 +-- docs/contributing/debugging.rst | 2 +- docs/contributing/development.rst | 2 +- docs/contributing/documentation.rst | 2 +- docs/contributing/issues-features.rst | 2 +- docs/interfaces/advanced-index.rst | 23 ---------------- docs/interfaces/basic-index.rst | 12 --------- docs/routing/bfd.rst | 2 +- docs/routing/ospf.rst | 2 +- docs/routing/rip.rst | 2 +- docs/services/conntrack.rst | 2 +- docs/services/ipoe-server.rst | 4 +-- docs/services/pppoe-server.rst | 2 +- docs/system/lcd.rst | 2 +- docs/vpn/sstp.rst | 2 +- 39 files changed, 97 insertions(+), 126 deletions(-) delete mode 100644 docs/interfaces/advanced-index.rst delete mode 100644 docs/interfaces/basic-index.rst diff --git a/docs/_ext/vyos.py b/docs/_ext/vyos.py index 89cc8ab7..4a974b46 100644 --- a/docs/_ext/vyos.py +++ b/docs/_ext/vyos.py @@ -3,7 +3,7 @@ import json import os from docutils import io, nodes, utils, statemachine from docutils.parsers.rst.roles import set_classes -from docutils.parsers.rst import Directive, directives +from docutils.parsers.rst import Directive, directives, states from sphinx.util.docutils import SphinxDirective @@ -173,7 +173,7 @@ class inlinecmd(nodes.inline): #self.literal_whitespace -= 1 -class CfgInclude(Directive): +class CfgInclude(SphinxDirective): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True @@ -189,10 +189,15 @@ class CfgInclude(Directive): 'var8': str, 'var9': str } + standard_include_path = os.path.join(os.path.dirname(states.__file__), + 'include') def run(self): ### Copy from include directive docutils """Include a file as part of the content of this reST file.""" + rel_filename, filename = self.env.relfn2path(self.arguments[0]) + self.arguments[0] = filename + self.env.note_included(filename) if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source( diff --git a/docs/_include/interface-common-with-dhcp.txt b/docs/_include/interface-common-with-dhcp.txt index 3e1394a3..1cacdd53 100644 --- a/docs/_include/interface-common-with-dhcp.txt +++ b/docs/_include/interface-common-with-dhcp.txt @@ -1,17 +1,17 @@ -.. cmdinclude:: ../_include/interface-address-with-dhcp.txt +.. cmdinclude:: /_include/interface-address-with-dhcp.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-common.txt +.. cmdinclude:: /_include/interface-common.txt :var0: {{ var0 }} :var1: {{ var1 }} **DHCP(v6)** -.. cmdinclude:: ../_include/interface-dhcp-options.txt +.. cmdinclude:: /_include/interface-dhcp-options.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-dhcpv6-options.txt +.. cmdinclude:: /_include/interface-dhcpv6-options.txt :var0: {{ var0 }} :var1: {{ var1 }} diff --git a/docs/_include/interface-common-without-dhcp.txt b/docs/_include/interface-common-without-dhcp.txt index d861f003..73d39dd0 100644 --- a/docs/_include/interface-common-without-dhcp.txt +++ b/docs/_include/interface-common-without-dhcp.txt @@ -1,7 +1,7 @@ -.. cmdinclude:: ../_include/interface-address.txt +.. cmdinclude:: /_include/interface-address.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-common.txt +.. cmdinclude:: /_include/interface-common.txt :var0: {{ var0 }} :var1: {{ var1 }} diff --git a/docs/_include/interface-common.txt b/docs/_include/interface-common.txt index de29356f..68c9c448 100644 --- a/docs/_include/interface-common.txt +++ b/docs/_include/interface-common.txt @@ -1,36 +1,36 @@ -.. cmdinclude:: ../_include/interface-description.txt +.. cmdinclude:: /_include/interface-description.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-disable.txt +.. cmdinclude:: /_include/interface-disable.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-disable-flow-control.txt +.. cmdinclude:: /_include/interface-disable-flow-control.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-disable-link-detect.txt +.. cmdinclude:: /_include/interface-disable-link-detect.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-mac.txt +.. cmdinclude:: /_include/interface-mac.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-mtu.txt +.. cmdinclude:: /_include/interface-mtu.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-ipv6-addr-autoconf.txt +.. cmdinclude:: /_include/interface-ipv6-addr-autoconf.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-ipv6-addr-eui64.txt +.. cmdinclude:: /_include/interface-ipv6-addr-eui64.txt :var0: {{ var0 }} :var1: {{ var1 }} -.. cmdinclude:: ../_include/interface-vrf.txt +.. cmdinclude:: /_include/interface-vrf.txt :var0: {{ var0 }} :var1: {{ var1 }} diff --git a/docs/_include/interface-dhcpv6-options.txt b/docs/_include/interface-dhcpv6-options.txt index a54a7dce..a47d9f32 100644 --- a/docs/_include/interface-dhcpv6-options.txt +++ b/docs/_include/interface-dhcpv6-options.txt @@ -30,7 +30,7 @@ set interfaces {{ var0 }} {{ var1 }} {{ var2 }} {{ var4 }} {{ var5 }} {{ var7 }} dhcpv6-options temporary -.. cmdinclude:: ../_include/interface-dhcpv6-prefix-delegation.txt +.. cmdinclude:: /_include/interface-dhcpv6-prefix-delegation.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: {{ var2 }} diff --git a/docs/_include/interface-vlan-8021ad.txt b/docs/_include/interface-vlan-8021ad.txt index a1e971be..12925ad4 100644 --- a/docs/_include/interface-vlan-8021ad.txt +++ b/docs/_include/interface-vlan-8021ad.txt @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt IEEE 802.1ad_ was an Ethernet networking standard informally known as QinQ as an amendment to IEEE standard 802.1q VLAN interfaces as described above. @@ -28,7 +28,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG (service tag with Ethernet Type = 0x88a8). -.. cmdinclude:: ../_include/interface-address-with-dhcp.txt +.. cmdinclude:: /_include/interface-address-with-dhcp.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -38,7 +38,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-description.txt +.. cmdinclude:: /_include/interface-description.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -48,7 +48,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-disable.txt +.. cmdinclude:: /_include/interface-disable.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -58,7 +58,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-disable-link-detect.txt +.. cmdinclude:: /_include/interface-disable-link-detect.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -68,7 +68,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-mac.txt +.. cmdinclude:: /_include/interface-mac.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -78,7 +78,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-mtu.txt +.. cmdinclude:: /_include/interface-mtu.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -88,7 +88,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-ipv6-addr-autoconf.txt +.. cmdinclude:: /_include/interface-ipv6-addr-autoconf.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -98,7 +98,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-ipv6-addr-eui64.txt +.. cmdinclude:: /_include/interface-ipv6-addr-eui64.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -108,7 +108,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-vrf.txt +.. cmdinclude:: /_include/interface-vrf.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -120,7 +120,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG **DHCP(v6)** -.. cmdinclude:: ../_include/interface-dhcp-options.txt +.. cmdinclude:: /_include/interface-dhcp-options.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -130,7 +130,7 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. cmdinclude:: ../_include/interface-dhcpv6-options.txt +.. cmdinclude:: /_include/interface-dhcpv6-options.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif-s @@ -140,4 +140,4 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/_include/interface-vlan-8021q.txt b/docs/_include/interface-vlan-8021q.txt index 2c7e58f7..37f652f3 100644 --- a/docs/_include/interface-vlan-8021q.txt +++ b/docs/_include/interface-vlan-8021q.txt @@ -29,63 +29,63 @@ term used for this is ``vif``. .. note:: Only 802.1Q-tagged packets are accepted on Ethernet vifs. -.. cmdinclude:: ../_include/interface-address-with-dhcp.txt +.. cmdinclude:: /_include/interface-address-with-dhcp.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-description.txt +.. cmdinclude:: /_include/interface-description.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-disable.txt +.. cmdinclude:: /_include/interface-disable.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-disable-link-detect.txt +.. cmdinclude:: /_include/interface-disable-link-detect.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-mac.txt +.. cmdinclude:: /_include/interface-mac.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-mtu.txt +.. cmdinclude:: /_include/interface-mtu.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-ipv6-addr-autoconf.txt +.. cmdinclude:: /_include/interface-ipv6-addr-autoconf.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-ipv6-addr-eui64.txt +.. cmdinclude:: /_include/interface-ipv6-addr-eui64.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-vrf.txt +.. cmdinclude:: /_include/interface-vrf.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif @@ -94,18 +94,18 @@ term used for this is ``vif``. **DHCP(v6)** -.. cmdinclude:: ../_include/interface-dhcp-options.txt +.. cmdinclude:: /_include/interface-dhcp-options.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. cmdinclude:: ../_include/interface-dhcpv6-options.txt +.. cmdinclude:: /_include/interface-dhcpv6-options.txt :var0: {{ var0 }} :var1: {{ var1 }} :var2: vif :var3: :var4: 10 -.. include:: ../common-references.rst \ No newline at end of file +.. include:: /common-references.rst \ No newline at end of file diff --git a/docs/configuration/firewall/index.rst b/docs/configuration/firewall/index.rst index 870e9a08..d9a3ebe3 100644 --- a/docs/configuration/firewall/index.rst +++ b/docs/configuration/firewall/index.rst @@ -3,6 +3,7 @@ Firewall ======== + Overview -------- diff --git a/docs/configuration/interfaces/bonding.rst b/docs/configuration/interfaces/bonding.rst index 7faddd6f..8ec8f34d 100644 --- a/docs/configuration/interfaces/bonding.rst +++ b/docs/configuration/interfaces/bonding.rst @@ -17,7 +17,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-with-dhcp.txt +.. cmdinclude:: /_include/interface-common-with-dhcp.txt :var0: bond :var1: bond0 @@ -259,7 +259,7 @@ Bond options VLAN ==== -.. cmdinclude:: ../_include/interface-vlan-8021q.txt +.. cmdinclude:: /_include/interface-vlan-8021q.txt :var0: bond :var1: bond0 diff --git a/docs/configuration/interfaces/bridge.rst b/docs/configuration/interfaces/bridge.rst index dc94a761..766d2aa5 100644 --- a/docs/configuration/interfaces/bridge.rst +++ b/docs/configuration/interfaces/bridge.rst @@ -21,7 +21,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-with-dhcp.txt +.. cmdinclude:: /_include/interface-common-with-dhcp.txt :var0: bridge :var1: br0 @@ -116,7 +116,7 @@ links providing fault tolerance if an active link fails. VLAN ==== -.. cmdinclude:: ../_include/interface-vlan-8021q.txt +.. cmdinclude:: /_include/interface-vlan-8021q.txt :var0: bridge :var1: br0 diff --git a/docs/configuration/interfaces/dummy.rst b/docs/configuration/interfaces/dummy.rst index c36d0024..c9845230 100644 --- a/docs/configuration/interfaces/dummy.rst +++ b/docs/configuration/interfaces/dummy.rst @@ -25,19 +25,19 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-address.txt +.. cmdinclude:: /_include/interface-address.txt :var0: dummy :var1: dum0 -.. cmdinclude:: ../_include/interface-description.txt +.. cmdinclude:: /_include/interface-description.txt :var0: dummy :var1: dum0 -.. cmdinclude:: ../_include/interface-disable.txt +.. cmdinclude:: /_include/interface-disable.txt :var0: dummy :var1: dum0 -.. cmdinclude:: ../_include/interface-vrf.txt +.. cmdinclude:: /_include/interface-vrf.txt :var0: dummy :var1: dum0 diff --git a/docs/configuration/interfaces/ethernet.rst b/docs/configuration/interfaces/ethernet.rst index f2ab3f67..9311c947 100644 --- a/docs/configuration/interfaces/ethernet.rst +++ b/docs/configuration/interfaces/ethernet.rst @@ -14,7 +14,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-with-dhcp.txt +.. cmdinclude:: /_include/interface-common-with-dhcp.txt :var0: ethernet :var1: eth0 @@ -72,14 +72,14 @@ VLAN Regular VLANs (802.1q) ---------------------- -.. cmdinclude:: ../_include/interface-vlan-8021q.txt +.. cmdinclude:: /_include/interface-vlan-8021q.txt :var0: ethernet :var1: eth0 QinQ (802.1ad) -------------- -.. cmdinclude:: ../_include/interface-vlan-8021ad.txt +.. cmdinclude:: /_include/interface-vlan-8021ad.txt :var0: ethernet :var1: eth0 diff --git a/docs/configuration/interfaces/geneve.rst b/docs/configuration/interfaces/geneve.rst index 47068687..9e00d621 100644 --- a/docs/configuration/interfaces/geneve.rst +++ b/docs/configuration/interfaces/geneve.rst @@ -39,7 +39,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-without-dhcp.txt +.. cmdinclude:: /_include/interface-common-without-dhcp.txt :var0: geneve :var1: gnv0 diff --git a/docs/configuration/interfaces/l2tpv3.rst b/docs/configuration/interfaces/l2tpv3.rst index 4c9cbf9b..a4b7be36 100644 --- a/docs/configuration/interfaces/l2tpv3.rst +++ b/docs/configuration/interfaces/l2tpv3.rst @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt .. _l2tpv3-interface: @@ -31,7 +31,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-without-dhcp.txt +.. cmdinclude:: /_include/interface-common-without-dhcp.txt :var0: l2tpv3 :var1: l2tpeth0 diff --git a/docs/configuration/interfaces/loopback.rst b/docs/configuration/interfaces/loopback.rst index a6d659b5..f7386c62 100644 --- a/docs/configuration/interfaces/loopback.rst +++ b/docs/configuration/interfaces/loopback.rst @@ -26,11 +26,11 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-address.txt +.. cmdinclude:: /_include/interface-address.txt :var0: loopback :var1: lo -.. cmdinclude:: ../_include/interface-description.txt +.. cmdinclude:: /_include/interface-description.txt :var0: loopback :var1: lo diff --git a/docs/configuration/interfaces/macsec.rst b/docs/configuration/interfaces/macsec.rst index ebc8f151..2bf643aa 100644 --- a/docs/configuration/interfaces/macsec.rst +++ b/docs/configuration/interfaces/macsec.rst @@ -20,7 +20,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-with-dhcp.txt +.. cmdinclude:: /_include/interface-common-with-dhcp.txt :var0: macsec :var1: macsec0 diff --git a/docs/configuration/interfaces/openvpn.rst b/docs/configuration/interfaces/openvpn.rst index c6934335..7646959c 100644 --- a/docs/configuration/interfaces/openvpn.rst +++ b/docs/configuration/interfaces/openvpn.rst @@ -581,4 +581,4 @@ The following commands let you reset OpenVPN. -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/configuration/interfaces/pppoe.rst b/docs/configuration/interfaces/pppoe.rst index 313edd84..decfd348 100644 --- a/docs/configuration/interfaces/pppoe.rst +++ b/docs/configuration/interfaces/pppoe.rst @@ -59,15 +59,15 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-description.txt +.. cmdinclude:: /_include/interface-description.txt :var0: pppoe :var1: pppoe0 -.. cmdinclude:: ../_include/interface-disable.txt +.. cmdinclude:: /_include/interface-disable.txt :var0: pppoe :var1: pppoe0 -.. cmdinclude:: ../_include/interface-vrf.txt +.. cmdinclude:: /_include/interface-vrf.txt :var0: pppoe :var1: pppoe0 @@ -177,7 +177,7 @@ IPv6 Use this command to enable acquisition of IPv6 address using stateless autoconfig (SLAAC). -.. cmdinclude:: ../_include/interface-dhcpv6-prefix-delegation.txt +.. cmdinclude:: /_include/interface-dhcpv6-prefix-delegation.txt :var0: pppoe :var1: pppoe0 diff --git a/docs/configuration/interfaces/pseudo-ethernet.rst b/docs/configuration/interfaces/pseudo-ethernet.rst index c2baca39..0471d2e1 100644 --- a/docs/configuration/interfaces/pseudo-ethernet.rst +++ b/docs/configuration/interfaces/pseudo-ethernet.rst @@ -45,7 +45,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-with-dhcp.txt +.. cmdinclude:: /_include/interface-common-with-dhcp.txt :var0: pseudo-ethernet :var1: peth0 @@ -60,6 +60,6 @@ Pseudo Ethernet/MACVLAN options VLAN ==== -.. cmdinclude:: ../_include/interface-vlan-8021q.txt +.. cmdinclude:: /_include/interface-vlan-8021q.txt :var0: pseudo-ethernet :var1: peth0 diff --git a/docs/configuration/interfaces/tunnel.rst b/docs/configuration/interfaces/tunnel.rst index 4b9da26b..7b1502f8 100644 --- a/docs/configuration/interfaces/tunnel.rst +++ b/docs/configuration/interfaces/tunnel.rst @@ -16,7 +16,7 @@ a closer look at the protocols and options currently supported by VyOS. Common interface configuration ------------------------------ -.. cmdinclude:: ../_include/interface-common-without-dhcp.txt +.. cmdinclude:: /_include/interface-common-without-dhcp.txt :var0: tunnel :var1: tun0 diff --git a/docs/configuration/interfaces/vxlan.rst b/docs/configuration/interfaces/vxlan.rst index 40dc5400..95f8de35 100644 --- a/docs/configuration/interfaces/vxlan.rst +++ b/docs/configuration/interfaces/vxlan.rst @@ -39,7 +39,7 @@ Configuration Common interface configuration ------------------------------ -.. cmdinclude:: ../_include/interface-common-without-dhcp.txt +.. cmdinclude:: /_include/interface-common-without-dhcp.txt :var0: vxlan :var1: vxlan0 diff --git a/docs/configuration/interfaces/wireless.rst b/docs/configuration/interfaces/wireless.rst index 2de3b126..82f66cf4 100644 --- a/docs/configuration/interfaces/wireless.rst +++ b/docs/configuration/interfaces/wireless.rst @@ -30,7 +30,7 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-common-with-dhcp.txt +.. cmdinclude:: /_include/interface-common-with-dhcp.txt :var0: wireless :var1: wlan0 @@ -378,14 +378,14 @@ VLAN Regular VLANs (802.1q) ---------------------- -.. cmdinclude:: ../_include/interface-vlan-8021q.txt +.. cmdinclude:: /_include/interface-vlan-8021q.txt :var0: wireless :var1: wlan0 QinQ (802.1ad) -------------- -.. cmdinclude:: ../_include/interface-vlan-8021ad.txt +.. cmdinclude:: /_include/interface-vlan-8021ad.txt :var0: wireless :var1: wlan0 diff --git a/docs/configuration/interfaces/wirelessmodem.rst b/docs/configuration/interfaces/wirelessmodem.rst index f9dfa228..a65a47f4 100644 --- a/docs/configuration/interfaces/wirelessmodem.rst +++ b/docs/configuration/interfaces/wirelessmodem.rst @@ -15,15 +15,15 @@ Configuration Common interface configuration ============================== -.. cmdinclude:: ../_include/interface-description.txt +.. cmdinclude:: /_include/interface-description.txt :var0: wirelessmodem :var1: wlm0 -.. cmdinclude:: ../_include/interface-disable.txt +.. cmdinclude:: /_include/interface-disable.txt :var0: wirelessmodem :var1: wlm0 -.. cmdinclude:: ../_include/interface-vrf.txt +.. cmdinclude:: /_include/interface-vrf.txt :var0: wirelessmodem :var1: wlm0 diff --git a/docs/configuration/nat/nptv6.rst b/docs/configuration/nat/nptv6.rst index f4e08325..c09c8336 100644 --- a/docs/configuration/nat/nptv6.rst +++ b/docs/configuration/nat/nptv6.rst @@ -1,4 +1,4 @@ -.. include:: _include/need_improvement.txt +.. include:: /_include/need_improvement.txt .. _nptv6: diff --git a/docs/configuration/policy/index.rst b/docs/configuration/policy/index.rst index 4be494e5..557911d9 100644 --- a/docs/configuration/policy/index.rst +++ b/docs/configuration/policy/index.rst @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt ###### Policy @@ -65,7 +65,7 @@ neighbor. You now see the longer AS path. -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt .. _routing-pbr: diff --git a/docs/contributing/debugging.rst b/docs/contributing/debugging.rst index ac2e0510..fcd62c89 100644 --- a/docs/contributing/debugging.rst +++ b/docs/contributing/debugging.rst @@ -143,4 +143,4 @@ order of the scripts. .. _vyatta-cfg: https://github.com/vyos/vyatta-cfg .. _bootchart.conf: https://github.com/vyos/vyos-build/blob/current/data/live-build-config/includes.chroot/etc/systemd/bootchart.conf -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/contributing/development.rst b/docs/contributing/development.rst index 86371845..0a7fecb5 100644 --- a/docs/contributing/development.rst +++ b/docs/contributing/development.rst @@ -711,4 +711,4 @@ http://dev.packages.vyos.net/repositories/. .. _`VLAN (VIF)`: https://github.com/vyos/vyos-1x/tree/current/interface-definitions/include/vif.xml.i .. _`MAC address`: https://github.com/vyos/vyos-1x/tree/current/interface-definitions/include/interface-mac.xml.i -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/contributing/documentation.rst b/docs/contributing/documentation.rst index 9dd0c495..0276a7d2 100644 --- a/docs/contributing/documentation.rst +++ b/docs/contributing/documentation.rst @@ -325,4 +325,4 @@ predefined structure. .. _reStructuredTextDirectives: https://docutils.sourceforge.io/docs/ref/rst/directives.html .. _README.md: https://github.com/vyos/vyos-documentation/blob/master/README.md -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/contributing/issues-features.rst b/docs/contributing/issues-features.rst index 60e49974..473d49d9 100644 --- a/docs/contributing/issues-features.rst +++ b/docs/contributing/issues-features.rst @@ -77,4 +77,4 @@ the left side under the specific project. .. _Slack: https://slack.vyos.io .. _Forum: https://forum.vyos.io -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/interfaces/advanced-index.rst b/docs/interfaces/advanced-index.rst deleted file mode 100644 index 7b9bde1e..00000000 --- a/docs/interfaces/advanced-index.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. _advanced_network-interfaces: - -################## -Network Interfaces -################## - -.. toctree:: - :maxdepth: 1 - - bond - bridge - dummy - ethernet - geneve - loopback - l2tpv3 - macsec - pppoe - pseudo-ethernet - tunnel - vxlan - wireless - wirelessmodem diff --git a/docs/interfaces/basic-index.rst b/docs/interfaces/basic-index.rst deleted file mode 100644 index 425792a2..00000000 --- a/docs/interfaces/basic-index.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _basic_network-interfaces: - -######################## -Basic Network Interfaces -######################## - -.. toctree:: - :maxdepth: 1 - - ethernet - loopback - pppoe diff --git a/docs/routing/bfd.rst b/docs/routing/bfd.rst index 1d494332..b8fdf489 100644 --- a/docs/routing/bfd.rst +++ b/docs/routing/bfd.rst @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt .. _routing-bfd: diff --git a/docs/routing/ospf.rst b/docs/routing/ospf.rst index fe05178b..19787b11 100644 --- a/docs/routing/ospf.rst +++ b/docs/routing/ospf.rst @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt .. _routing-ospf: diff --git a/docs/routing/rip.rst b/docs/routing/rip.rst index 68868e37..0d73ad34 100644 --- a/docs/routing/rip.rst +++ b/docs/routing/rip.rst @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt .. _rip: diff --git a/docs/services/conntrack.rst b/docs/services/conntrack.rst index c361d293..55cd088e 100644 --- a/docs/services/conntrack.rst +++ b/docs/services/conntrack.rst @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt Conntrack --------- diff --git a/docs/services/ipoe-server.rst b/docs/services/ipoe-server.rst index 3aedf966..279f0c6d 100644 --- a/docs/services/ipoe-server.rst +++ b/docs/services/ipoe-server.rst @@ -1,4 +1,4 @@ -.. include:: ../_include/need_improvement.txt +.. include:: /_include/need_improvement.txt .. _ipoe_server: @@ -146,4 +146,4 @@ The rate-limit is set in kbit/sec. -------+------------+-------------------+-------------+-----+--------+------------+--------+----------+------------------ ipoe0 | eth2 | 08:00:27:2f:d8:06 | 192.168.0.2 | | | 500/500 | active | 00:00:05 | dccc870fd31349fb -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/services/pppoe-server.rst b/docs/services/pppoe-server.rst index e710ba6a..4deb6c7e 100644 --- a/docs/services/pppoe-server.rst +++ b/docs/services/pppoe-server.rst @@ -394,4 +394,4 @@ a /56 subnet for the clients internal use. --------+----------+-------------+--------------------------+---------------------+-------------------+------------+--------+----------+----------+---------- ppp0 | test | 192.168.0.1 | 2001:db8:8002:0:200::/64 | 2001:db8:8003::1/56 | 00:53:00:12:42:eb | | active | 00:00:49 | 875 B | 2.1 KiB -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/system/lcd.rst b/docs/system/lcd.rst index 441becf5..2509946e 100644 --- a/docs/system/lcd.rst +++ b/docs/system/lcd.rst @@ -41,5 +41,5 @@ Configuration .. note:: We can't support all displays from the beginning. If your display type is missing, please create a feature request via Phabricator_. -.. include:: ../common-references.rst +.. include:: /common-references.rst diff --git a/docs/vpn/sstp.rst b/docs/vpn/sstp.rst index e5567cb6..f5e4ad05 100644 --- a/docs/vpn/sstp.rst +++ b/docs/vpn/sstp.rst @@ -344,4 +344,4 @@ A connection attempt will be shown as: .. _sstpc: https://github.com/reliablehosting/sstp-client -.. include:: ../common-references.rst +.. include:: /common-references.rst From 8943fc9f877cbee3301a8261ddd27b4b1f15f174 Mon Sep 17 00:00:00 2001 From: rebortg Date: Mon, 30 Nov 2020 20:53:36 +0100 Subject: [PATCH 21/28] arrange services and protocols --- docs/configuration/firewall/index.rst | 65 +++++++ .../protocols}/bfd.rst | 0 .../protocols}/bgp.rst | 0 docs/configuration/protocols/igmp-proxy.rst | 2 + .../protocols/igmp.rst} | 0 docs/configuration/protocols/index.rst | 22 +++ .../protocols}/mpls.rst | 0 docs/configuration/protocols/ospf.rst | 70 ++++++++ .../protocols/ospfv3.rst} | 70 -------- docs/configuration/protocols/pim.rst | 2 + .../protocols}/rip.rst | 0 docs/configuration/protocols/ripng.rst | 3 + .../protocols}/rpki.rst | 0 .../protocols}/static.rst | 61 +++++++ docs/configuration/protocols/vrf.rst | 3 + .../service/broadcast-relay.rst} | 0 .../service/conntrack-sync.rst} | 0 .../service}/console-server.rst | 0 docs/configuration/service/dhcp-relay.rst | 2 + .../service/dhcp-server.rst} | 0 docs/configuration/service/dhcpv6-relay.rst | 2 + docs/configuration/service/dhcpv6-server.rst | 2 + .../service/dns.rst} | 166 ++++++++++++++++++ .../service/https.rst} | 0 docs/configuration/service/index.rst | 29 +++ .../service}/ipoe-server.rst | 0 .../service}/lldp.rst | 0 .../service/mdns.rst} | 0 docs/configuration/service/pppoe-advert.rst | 2 + .../service}/pppoe-server.rst | 0 .../service}/router-advert.rst | 0 docs/configuration/service/salt-minion.rst | 2 + .../service}/snmp.rst | 0 .../service}/ssh.rst | 0 .../service/tftp-server.rst} | 0 .../service}/webproxy.rst | 0 docs/operation/index.rst | 10 ++ docs/{routing => operation}/ip-commands.rst | 0 docs/routing/arp.rst | 59 ------- docs/routing/index.rst | 22 --- docs/routing/mss-clamp.rst | 63 ------- docs/services/dynamic-dns.rst | 164 ----------------- docs/services/index.rst | 26 --- 43 files changed, 443 insertions(+), 404 deletions(-) rename docs/{routing => configuration/protocols}/bfd.rst (100%) rename docs/{routing => configuration/protocols}/bgp.rst (100%) create mode 100644 docs/configuration/protocols/igmp-proxy.rst rename docs/{routing/multicast.rst => configuration/protocols/igmp.rst} (100%) create mode 100644 docs/configuration/protocols/index.rst rename docs/{routing => configuration/protocols}/mpls.rst (100%) create mode 100644 docs/configuration/protocols/ospf.rst rename docs/{routing/ospf.rst => configuration/protocols/ospfv3.rst} (52%) create mode 100644 docs/configuration/protocols/pim.rst rename docs/{routing => configuration/protocols}/rip.rst (100%) create mode 100644 docs/configuration/protocols/ripng.rst rename docs/{routing => configuration/protocols}/rpki.rst (100%) rename docs/{routing => configuration/protocols}/static.rst (73%) create mode 100644 docs/configuration/protocols/vrf.rst rename docs/{services/udp-broadcast-relay.rst => configuration/service/broadcast-relay.rst} (100%) rename docs/{services/conntrack.rst => configuration/service/conntrack-sync.rst} (100%) rename docs/{services => configuration/service}/console-server.rst (100%) create mode 100644 docs/configuration/service/dhcp-relay.rst rename docs/{services/dhcp.rst => configuration/service/dhcp-server.rst} (100%) create mode 100644 docs/configuration/service/dhcpv6-relay.rst create mode 100644 docs/configuration/service/dhcpv6-server.rst rename docs/{services/dns-forwarding.rst => configuration/service/dns.rst} (54%) rename docs/{automation/http-api.rst => configuration/service/https.rst} (100%) create mode 100644 docs/configuration/service/index.rst rename docs/{services => configuration/service}/ipoe-server.rst (100%) rename docs/{services => configuration/service}/lldp.rst (100%) rename docs/{services/mdns-repeater.rst => configuration/service/mdns.rst} (100%) create mode 100644 docs/configuration/service/pppoe-advert.rst rename docs/{services => configuration/service}/pppoe-server.rst (100%) rename docs/{services => configuration/service}/router-advert.rst (100%) create mode 100644 docs/configuration/service/salt-minion.rst rename docs/{services => configuration/service}/snmp.rst (100%) rename docs/{services => configuration/service}/ssh.rst (100%) rename docs/{services/tftp.rst => configuration/service/tftp-server.rst} (100%) rename docs/{services => configuration/service}/webproxy.rst (100%) create mode 100644 docs/operation/index.rst rename docs/{routing => operation}/ip-commands.rst (100%) delete mode 100644 docs/routing/arp.rst delete mode 100644 docs/routing/index.rst delete mode 100644 docs/routing/mss-clamp.rst delete mode 100644 docs/services/dynamic-dns.rst delete mode 100644 docs/services/index.rst diff --git a/docs/configuration/firewall/index.rst b/docs/configuration/firewall/index.rst index d9a3ebe3..2615774f 100644 --- a/docs/configuration/firewall/index.rst +++ b/docs/configuration/firewall/index.rst @@ -766,3 +766,68 @@ Example Partial Config } } } + + +.. _routing-mss-clamp: + +################ +TCP-MSS Clamping +################ + +As Internet wide PMTU discovery rarely works, we sometimes need to clamp +our TCP MSS value to a specific value. This is a field in the TCP +Options part of a SYN packet. By setting the MSS value, you are telling +the remote side unequivocally 'do not try to send me packets bigger than +this value'. + +Starting with VyOS 1.2 there is a firewall option to clamp your TCP MSS +value for IPv4 and IPv6. + + +.. note:: MSS value = MTU - 20 (IP header) - 20 (TCP header), resulting + in 1452 bytes on a 1492 byte MTU. + + +IPv4 +==== + +.. cfgcmd:: set firewall options interface adjust-mss + + Use this command to set the maximum segment size for IPv4 transit + packets on a specific interface (500-1460 bytes). + +Example +------- + +Clamp outgoing MSS value in a TCP SYN packet to `1452` for `pppoe0` and +`1372` +for your WireGuard `wg02` tunnel. + +.. code-block:: none + + set firewall options interface pppoe0 adjust-mss '1452' + set firewall options interface wg02 adjust-mss '1372' + +IPv6 +==== + +.. cfgcmd:: set firewall options interface adjust-mss6 + + Use this command to set the maximum segment size for IPv6 transit + packets on a specific interface (1280-1492 bytes). + +Example +------- + +Clamp outgoing MSS value in a TCP SYN packet to `1280` for both `pppoe0` and +`wg02` interface. + +.. code-block:: none + + set firewall options interface pppoe0 adjust-mss6 '1280' + set firewall options interface wg02 adjust-mss6 '1280' + + + +.. hint:: When doing your byte calculations, you might find useful this + `Visual packet size calculator `_. diff --git a/docs/routing/bfd.rst b/docs/configuration/protocols/bfd.rst similarity index 100% rename from docs/routing/bfd.rst rename to docs/configuration/protocols/bfd.rst diff --git a/docs/routing/bgp.rst b/docs/configuration/protocols/bgp.rst similarity index 100% rename from docs/routing/bgp.rst rename to docs/configuration/protocols/bgp.rst diff --git a/docs/configuration/protocols/igmp-proxy.rst b/docs/configuration/protocols/igmp-proxy.rst new file mode 100644 index 00000000..cce5f948 --- /dev/null +++ b/docs/configuration/protocols/igmp-proxy.rst @@ -0,0 +1,2 @@ +igmp-proxy +########## \ No newline at end of file diff --git a/docs/routing/multicast.rst b/docs/configuration/protocols/igmp.rst similarity index 100% rename from docs/routing/multicast.rst rename to docs/configuration/protocols/igmp.rst diff --git a/docs/configuration/protocols/index.rst b/docs/configuration/protocols/index.rst new file mode 100644 index 00000000..271b6056 --- /dev/null +++ b/docs/configuration/protocols/index.rst @@ -0,0 +1,22 @@ +######### +Protocols +######### + + +.. toctree:: + :maxdepth: 1 + :includehidden: + + bfd + bgp + igmp + igmp-proxy + mpls + ospf + ospfv3 + pim + rip + ripng + rpki + static + vrf diff --git a/docs/routing/mpls.rst b/docs/configuration/protocols/mpls.rst similarity index 100% rename from docs/routing/mpls.rst rename to docs/configuration/protocols/mpls.rst diff --git a/docs/configuration/protocols/ospf.rst b/docs/configuration/protocols/ospf.rst new file mode 100644 index 00000000..ff7c5e64 --- /dev/null +++ b/docs/configuration/protocols/ospf.rst @@ -0,0 +1,70 @@ +.. include:: /_include/need_improvement.txt + +.. _routing-ospf: + +#### +OSPF +#### + +:abbr:`OSPF (Open Shortest Path First)` is a routing protocol for Internet +Protocol (IP) networks. It uses a link state routing (LSR) algorithm and falls +into the group of interior gateway protocols (IGPs), operating within a single +autonomous system (AS). It is defined as OSPF Version 2 in :rfc:`2328` (1998) +for IPv4. Updates for IPv6 are specified as OSPF Version 3 in :rfc:`5340` +(2008). OSPF supports the :abbr:`CIDR (Classless Inter-Domain Routing)` +addressing model. + +OSPF is a widely used IGP in large enterprise networks. + +OSPFv2 (IPv4) +############# + +In order to have a VyOS system exchanging routes with OSPF neighbors, you will +at least need to configure an OSPF area and some network. + +.. code-block:: none + + set protocols ospf area 0 network 192.168.0.0/24 + +That is the minimum configuration you will need. +It is a good practice to define the router ID too. + +.. code-block:: none + + set protocols ospf parameters router-id 10.1.1.1 + + +Below you can see a typical configuration using 2 nodes, redistribute loopback +address and the node 1 sending the default route: + +**Node 1** + +.. code-block:: none + + set interfaces loopback lo address 10.1.1.1/32 + set protocols ospf area 0 network 192.168.0.0/24 + set protocols ospf default-information originate always + set protocols ospf default-information originate metric 10 + set protocols ospf default-information originate metric-type 2 + set protocols ospf log-adjacency-changes + set protocols ospf parameters router-id 10.1.1.1 + set protocols ospf redistribute connected metric-type 2 + set protocols ospf redistribute connected route-map CONNECT + + set policy route-map CONNECT rule 10 action permit + set policy route-map CONNECT rule 10 match interface lo + +**Node 2** + +.. code-block:: none + + set interfaces loopback lo address 10.2.2.2/32 + set protocols ospf area 0 network 192.168.0.0/24 + set protocols ospf log-adjacency-changes + set protocols ospf parameters router-id 10.2.2.2 + set protocols ospf redistribute connected metric-type 2 + set protocols ospf redistribute connected route-map CONNECT + + set policy route-map CONNECT rule 10 action permit + set policy route-map CONNECT rule 10 match interface lo + diff --git a/docs/routing/ospf.rst b/docs/configuration/protocols/ospfv3.rst similarity index 52% rename from docs/routing/ospf.rst rename to docs/configuration/protocols/ospfv3.rst index 19787b11..f0e28983 100644 --- a/docs/routing/ospf.rst +++ b/docs/configuration/protocols/ospfv3.rst @@ -1,73 +1,3 @@ -.. include:: /_include/need_improvement.txt - -.. _routing-ospf: - -#### -OSPF -#### - -:abbr:`OSPF (Open Shortest Path First)` is a routing protocol for Internet -Protocol (IP) networks. It uses a link state routing (LSR) algorithm and falls -into the group of interior gateway protocols (IGPs), operating within a single -autonomous system (AS). It is defined as OSPF Version 2 in :rfc:`2328` (1998) -for IPv4. Updates for IPv6 are specified as OSPF Version 3 in :rfc:`5340` -(2008). OSPF supports the :abbr:`CIDR (Classless Inter-Domain Routing)` -addressing model. - -OSPF is a widely used IGP in large enterprise networks. - -OSPFv2 (IPv4) -############# - -In order to have a VyOS system exchanging routes with OSPF neighbors, you will -at least need to configure an OSPF area and some network. - -.. code-block:: none - - set protocols ospf area 0 network 192.168.0.0/24 - -That is the minimum configuration you will need. -It is a good practice to define the router ID too. - -.. code-block:: none - - set protocols ospf parameters router-id 10.1.1.1 - - -Below you can see a typical configuration using 2 nodes, redistribute loopback -address and the node 1 sending the default route: - -**Node 1** - -.. code-block:: none - - set interfaces loopback lo address 10.1.1.1/32 - set protocols ospf area 0 network 192.168.0.0/24 - set protocols ospf default-information originate always - set protocols ospf default-information originate metric 10 - set protocols ospf default-information originate metric-type 2 - set protocols ospf log-adjacency-changes - set protocols ospf parameters router-id 10.1.1.1 - set protocols ospf redistribute connected metric-type 2 - set protocols ospf redistribute connected route-map CONNECT - - set policy route-map CONNECT rule 10 action permit - set policy route-map CONNECT rule 10 match interface lo - -**Node 2** - -.. code-block:: none - - set interfaces loopback lo address 10.2.2.2/32 - set protocols ospf area 0 network 192.168.0.0/24 - set protocols ospf log-adjacency-changes - set protocols ospf parameters router-id 10.2.2.2 - set protocols ospf redistribute connected metric-type 2 - set protocols ospf redistribute connected route-map CONNECT - - set policy route-map CONNECT rule 10 action permit - set policy route-map CONNECT rule 10 match interface lo - OSPFv3 (IPv6) ############# diff --git a/docs/configuration/protocols/pim.rst b/docs/configuration/protocols/pim.rst new file mode 100644 index 00000000..1dd373d8 --- /dev/null +++ b/docs/configuration/protocols/pim.rst @@ -0,0 +1,2 @@ +PIM +### \ No newline at end of file diff --git a/docs/routing/rip.rst b/docs/configuration/protocols/rip.rst similarity index 100% rename from docs/routing/rip.rst rename to docs/configuration/protocols/rip.rst diff --git a/docs/configuration/protocols/ripng.rst b/docs/configuration/protocols/ripng.rst new file mode 100644 index 00000000..dec6bddf --- /dev/null +++ b/docs/configuration/protocols/ripng.rst @@ -0,0 +1,3 @@ +##### +RIPng +##### \ No newline at end of file diff --git a/docs/routing/rpki.rst b/docs/configuration/protocols/rpki.rst similarity index 100% rename from docs/routing/rpki.rst rename to docs/configuration/protocols/rpki.rst diff --git a/docs/routing/static.rst b/docs/configuration/protocols/static.rst similarity index 73% rename from docs/routing/static.rst rename to docs/configuration/protocols/static.rst index 523627fa..fbde8228 100644 --- a/docs/routing/static.rst +++ b/docs/configuration/protocols/static.rst @@ -132,3 +132,64 @@ TBD Alternate routing tables are used with policy based routing of by utilizing :ref:`vrf`. + + +.. _routing-arp: + +### +ARP +### + +:abbr:`ARP (Address Resolution Protocol)` is a communication protocol used for +discovering the link layer address, such as a MAC address, associated with a +given internet layer address, typically an IPv4 address. This mapping is a +critical function in the Internet protocol suite. ARP was defined in 1982 by +:rfc:`826` which is Internet Standard STD 37. + +In Internet Protocol Version 6 (IPv6) networks, the functionality of ARP is +provided by the Neighbor Discovery Protocol (NDP). + +To manipulate or display ARP_ table entries, the following commands are +implemented. + +Configure +========= + +.. cfgcmd:: set protocols static arp

hwaddr + + This will configure a static ARP entry always resolving `
` to + ``. + + Example: + + .. code-block:: none + + set protocols static arp 192.0.2.100 hwaddr 00:53:27:de:23:aa + +Operation +========= + +.. opcmd:: show protocols static arp + + Display all known ARP table entries spanning across all interfaces + +.. code-block:: none + + vyos@vyos:~$ show protocols static arp + Address HWtype HWaddress Flags Mask Iface + 10.1.1.1 ether 00:53:00:de:23:2e C eth1 + 10.1.1.100 ether 00:53:00:de:23:aa CM eth1 + + +.. opcmd:: show protocols static arp interface eth1 + + Display all known ARP table entries on a given interface only (`eth1`): + +.. code-block:: none + + vyos@vyos:~$ show protocols static arp interface eth1 + Address HWtype HWaddress Flags Mask Iface + 10.1.1.1 ether 00:53:00:de:23:2e C eth1 + 10.1.1.100 ether 00:53:00:de:23:aa CM eth1 + +.. _ARP: https://en.wikipedia.org/wiki/Address_Resolution_Protocol diff --git a/docs/configuration/protocols/vrf.rst b/docs/configuration/protocols/vrf.rst new file mode 100644 index 00000000..e7609a77 --- /dev/null +++ b/docs/configuration/protocols/vrf.rst @@ -0,0 +1,3 @@ +############# +Protocols VRF +############# diff --git a/docs/services/udp-broadcast-relay.rst b/docs/configuration/service/broadcast-relay.rst similarity index 100% rename from docs/services/udp-broadcast-relay.rst rename to docs/configuration/service/broadcast-relay.rst diff --git a/docs/services/conntrack.rst b/docs/configuration/service/conntrack-sync.rst similarity index 100% rename from docs/services/conntrack.rst rename to docs/configuration/service/conntrack-sync.rst diff --git a/docs/services/console-server.rst b/docs/configuration/service/console-server.rst similarity index 100% rename from docs/services/console-server.rst rename to docs/configuration/service/console-server.rst diff --git a/docs/configuration/service/dhcp-relay.rst b/docs/configuration/service/dhcp-relay.rst new file mode 100644 index 00000000..445519b3 --- /dev/null +++ b/docs/configuration/service/dhcp-relay.rst @@ -0,0 +1,2 @@ +dhcp-relay +########## \ No newline at end of file diff --git a/docs/services/dhcp.rst b/docs/configuration/service/dhcp-server.rst similarity index 100% rename from docs/services/dhcp.rst rename to docs/configuration/service/dhcp-server.rst diff --git a/docs/configuration/service/dhcpv6-relay.rst b/docs/configuration/service/dhcpv6-relay.rst new file mode 100644 index 00000000..2d105fdf --- /dev/null +++ b/docs/configuration/service/dhcpv6-relay.rst @@ -0,0 +1,2 @@ +dhcpv6-relay +############ \ No newline at end of file diff --git a/docs/configuration/service/dhcpv6-server.rst b/docs/configuration/service/dhcpv6-server.rst new file mode 100644 index 00000000..64e523a0 --- /dev/null +++ b/docs/configuration/service/dhcpv6-server.rst @@ -0,0 +1,2 @@ +dhcpv6-server +############# \ No newline at end of file diff --git a/docs/services/dns-forwarding.rst b/docs/configuration/service/dns.rst similarity index 54% rename from docs/services/dns-forwarding.rst rename to docs/configuration/service/dns.rst index 5c154fdf..f332c55c 100644 --- a/docs/services/dns-forwarding.rst +++ b/docs/configuration/service/dns.rst @@ -145,3 +145,169 @@ Operation .. opcmd:: restart dns forwarding Restarts the DNS recursor process. This also invalidates the local DNS forwarding cache. + + +.. _dynamic-dns: + +########### +Dynamic DNS +########### + +VyOS is able to update a remote DNS record when an interface gets a new IP +address. In order to do so, VyOS includes ddclient_, a Perl script written for +this only one purpose. + +ddclient_ uses two methods to update a DNS record. The first one will send +updates directly to the DNS daemon, in compliance with :rfc:`2136`. The second +one involves a third party service, like DynDNS.com or any other similar +website. This method uses HTTP requests to transmit the new IP address. You +can configure both in VyOS. + +Configuration +============= + +:rfc:`2136` Based +----------------- + +.. cfgcmd:: set service dns dynamic interface rfc2136 + + Create new :rfc:`2136` DNS update configuration which will update the IP + address assigned to `` on the service you configured under + ``. + +.. cfgcmd:: set service dns dynamic interface rfc2136 key + + File identified by `` containing the secret RNDC key shared with + remote DNS server. + +.. cfgcmd:: set service dns dynamic interface rfc2136 server + + Configure the DNS `` IP/FQDN used when updating this dynamic + assignment. + +.. cfgcmd:: set service dns dynamic interface rfc2136 zone + + Configure DNS `` to be updated. + +.. cfgcmd:: set service dns dynamic interface rfc2136 record + + Configure DNS `` which should be updated. This can be set multiple + times. + +.. cfgcmd:: set service dns dynamic interface rfc2136 ttl + + Configure optional TTL value on the given resource record. This defualts to + 600 seconds. + +Example +^^^^^^^ + +* Register DNS record ``example.vyos.io`` on DNS server ``ns1.vyos.io`` +* Use auth key file at ``/config/auth/my.key`` +* Set TTL to 300 seconds + +.. code-block:: none + + vyos@vyos# show service dns dynamic + interface eth0.7 { + rfc2136 VyOS-DNS { + key /config/auth/my.key + record example.vyos.io + server ns1.vyos.io + ttl 300 + zone vyos.io + } + } + +This will render the following ddclient_ configuration entry: + +.. code-block:: none + + # + # ddclient configuration for interface "eth0.7": + # + use=if, if=eth0.7 + + # RFC2136 dynamic DNS configuration for example.vyos.io.vyos.io + server=ns1.vyos.io + protocol=nsupdate + password=/config/auth/my.key + ttl=300 + zone=vyos.io + example.vyos.io + +.. note:: You can also keep different DNS zone updated. Just create a new + config node: ``set service dns dynamic interface rfc2136 + `` + +HTTP based services +------------------- + +VyOS is also able to use any service relying on protocols supported by ddclient. + +To use such a service, one must define a login, password, one or multiple +hostnames, protocol and server. + +.. cfgcmd:: set service dns dynamic interface service host-name + + Setup the dynamic DNS hostname `` associated with the DynDNS + provider identified by `` when the IP address on interface + `` changes. + +.. cfgcmd:: set service dns dynamic interface service login + + Configure `` used when authenticating the update request for + DynDNS service identified by ``. + For Namecheap, set the you wish to update. + +.. cfgcmd:: set service dns dynamic interface service password + + Configure `` used when authenticating the update request for + DynDNS service identified by ``. + +.. cfgcmd:: set service dns dynamic interface service protocol + + When a ``custom`` DynDNS provider is used the protocol used for communicating + to the provider must be specified under ``. See the embedded + completion helper for available protocols. + +.. cfgcmd:: set service dns dynamic interface service server + + When a ``custom`` DynDNS provider is used the `` where update + requests are being sent to must be specified. + +Example: +^^^^^^^^ + +Use DynDNS as your preferred provider: + +.. code-block:: none + + set service dns dynamic interface eth0 service dyndns + set service dns dynamic interface eth0 service dyndns login my-login + set service dns dynamic interface eth0 service dyndns password my-password + set service dns dynamic interface eth0 service dyndns host-name my-dyndns-hostname + +.. note:: Multiple services can be used per interface. Just specify as many + serives per interface as you like! + +Running Behind NAT +------------------ + +By default, ddclient_ will update a dynamic dns record using the IP address +directly attached to the interface. If your VyOS instance is behind NAT, your +record will be updated to point to your internal IP. + +ddclient_ has another way to determine the WAN IP address. This is controlled +by: + +.. cfgcmd:: set service dns dynamic interface use-web url + + Use configured `` to determine your IP address. ddclient_ will load + `` and tries to extract your IP address from the response. + +.. cfgcmd:: set service dns dynamic interface use-web skip + + ddclient_ will skip any address located before the string set in ``. + +.. _ddclient: https://github.com/ddclient/ddclient diff --git a/docs/automation/http-api.rst b/docs/configuration/service/https.rst similarity index 100% rename from docs/automation/http-api.rst rename to docs/configuration/service/https.rst diff --git a/docs/configuration/service/index.rst b/docs/configuration/service/index.rst new file mode 100644 index 00000000..0ef2bbd3 --- /dev/null +++ b/docs/configuration/service/index.rst @@ -0,0 +1,29 @@ +####### +Service +####### + + +.. toctree:: + :maxdepth: 1 + :includehidden: + + broadcast-relay + conntrack-sync + console-server + dhcp-relay + dhcp-server + dhcpv6-relay + dhcpv6-server + dns + https + ipoe-server + lldp + mdns + pppoe-advert + pppoe-server + router-advert + salt-minion + snmp + ssh + tftp-server + webproxy diff --git a/docs/services/ipoe-server.rst b/docs/configuration/service/ipoe-server.rst similarity index 100% rename from docs/services/ipoe-server.rst rename to docs/configuration/service/ipoe-server.rst diff --git a/docs/services/lldp.rst b/docs/configuration/service/lldp.rst similarity index 100% rename from docs/services/lldp.rst rename to docs/configuration/service/lldp.rst diff --git a/docs/services/mdns-repeater.rst b/docs/configuration/service/mdns.rst similarity index 100% rename from docs/services/mdns-repeater.rst rename to docs/configuration/service/mdns.rst diff --git a/docs/configuration/service/pppoe-advert.rst b/docs/configuration/service/pppoe-advert.rst new file mode 100644 index 00000000..bbb82202 --- /dev/null +++ b/docs/configuration/service/pppoe-advert.rst @@ -0,0 +1,2 @@ +pppoe-advert +############ \ No newline at end of file diff --git a/docs/services/pppoe-server.rst b/docs/configuration/service/pppoe-server.rst similarity index 100% rename from docs/services/pppoe-server.rst rename to docs/configuration/service/pppoe-server.rst diff --git a/docs/services/router-advert.rst b/docs/configuration/service/router-advert.rst similarity index 100% rename from docs/services/router-advert.rst rename to docs/configuration/service/router-advert.rst diff --git a/docs/configuration/service/salt-minion.rst b/docs/configuration/service/salt-minion.rst new file mode 100644 index 00000000..63df57a4 --- /dev/null +++ b/docs/configuration/service/salt-minion.rst @@ -0,0 +1,2 @@ +salt-minion +########### \ No newline at end of file diff --git a/docs/services/snmp.rst b/docs/configuration/service/snmp.rst similarity index 100% rename from docs/services/snmp.rst rename to docs/configuration/service/snmp.rst diff --git a/docs/services/ssh.rst b/docs/configuration/service/ssh.rst similarity index 100% rename from docs/services/ssh.rst rename to docs/configuration/service/ssh.rst diff --git a/docs/services/tftp.rst b/docs/configuration/service/tftp-server.rst similarity index 100% rename from docs/services/tftp.rst rename to docs/configuration/service/tftp-server.rst diff --git a/docs/services/webproxy.rst b/docs/configuration/service/webproxy.rst similarity index 100% rename from docs/services/webproxy.rst rename to docs/configuration/service/webproxy.rst diff --git a/docs/operation/index.rst b/docs/operation/index.rst new file mode 100644 index 00000000..b40f769d --- /dev/null +++ b/docs/operation/index.rst @@ -0,0 +1,10 @@ +############## +Operation Mode +############## + +.. toctree:: + :maxdepth: 1 + :includehidden: + + information + ip-command \ No newline at end of file diff --git a/docs/routing/ip-commands.rst b/docs/operation/ip-commands.rst similarity index 100% rename from docs/routing/ip-commands.rst rename to docs/operation/ip-commands.rst diff --git a/docs/routing/arp.rst b/docs/routing/arp.rst deleted file mode 100644 index 5f3115ab..00000000 --- a/docs/routing/arp.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. _routing-arp: - -### -ARP -### - -:abbr:`ARP (Address Resolution Protocol)` is a communication protocol used for -discovering the link layer address, such as a MAC address, associated with a -given internet layer address, typically an IPv4 address. This mapping is a -critical function in the Internet protocol suite. ARP was defined in 1982 by -:rfc:`826` which is Internet Standard STD 37. - -In Internet Protocol Version 6 (IPv6) networks, the functionality of ARP is -provided by the Neighbor Discovery Protocol (NDP). - -To manipulate or display ARP_ table entries, the following commands are -implemented. - -Configure -========= - -.. cfgcmd:: set protocols static arp
hwaddr - - This will configure a static ARP entry always resolving `
` to - ``. - - Example: - - .. code-block:: none - - set protocols static arp 192.0.2.100 hwaddr 00:53:27:de:23:aa - -Operation -========= - -.. opcmd:: show protocols static arp - - Display all known ARP table entries spanning across all interfaces - -.. code-block:: none - - vyos@vyos:~$ show protocols static arp - Address HWtype HWaddress Flags Mask Iface - 10.1.1.1 ether 00:53:00:de:23:2e C eth1 - 10.1.1.100 ether 00:53:00:de:23:aa CM eth1 - - -.. opcmd:: show protocols static arp interface eth1 - - Display all known ARP table entries on a given interface only (`eth1`): - -.. code-block:: none - - vyos@vyos:~$ show protocols static arp interface eth1 - Address HWtype HWaddress Flags Mask Iface - 10.1.1.1 ether 00:53:00:de:23:2e C eth1 - 10.1.1.100 ether 00:53:00:de:23:aa CM eth1 - -.. _ARP: https://en.wikipedia.org/wiki/Address_Resolution_Protocol diff --git a/docs/routing/index.rst b/docs/routing/index.rst deleted file mode 100644 index 63d7c7d8..00000000 --- a/docs/routing/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. _routing: - -####### -Routing -####### - -.. toctree:: - :maxdepth: 1 - - arp - bfd - bgp - mpls - mss-clamp - multicast - ip-commands - ospf - pbr - rip - policy - rpki - static diff --git a/docs/routing/mss-clamp.rst b/docs/routing/mss-clamp.rst deleted file mode 100644 index 3fdd1153..00000000 --- a/docs/routing/mss-clamp.rst +++ /dev/null @@ -1,63 +0,0 @@ -.. _routing-mss-clamp: - -################ -TCP-MSS Clamping -################ - -As Internet wide PMTU discovery rarely works, we sometimes need to clamp -our TCP MSS value to a specific value. This is a field in the TCP -Options part of a SYN packet. By setting the MSS value, you are telling -the remote side unequivocally 'do not try to send me packets bigger than -this value'. - -Starting with VyOS 1.2 there is a firewall option to clamp your TCP MSS -value for IPv4 and IPv6. - - -.. note:: MSS value = MTU - 20 (IP header) - 20 (TCP header), resulting - in 1452 bytes on a 1492 byte MTU. - - -IPv4 -==== - -.. cfgcmd:: set firewall options interface adjust-mss - - Use this command to set the maximum segment size for IPv4 transit - packets on a specific interface (500-1460 bytes). - -Example -------- - -Clamp outgoing MSS value in a TCP SYN packet to `1452` for `pppoe0` and -`1372` -for your WireGuard `wg02` tunnel. - -.. code-block:: none - - set firewall options interface pppoe0 adjust-mss '1452' - set firewall options interface wg02 adjust-mss '1372' - -IPv6 -==== - -.. cfgcmd:: set firewall options interface adjust-mss6 - - Use this command to set the maximum segment size for IPv6 transit - packets on a specific interface (1280-1492 bytes). - -Example -------- - -Clamp outgoing MSS value in a TCP SYN packet to `1280` for both `pppoe0` and -`wg02` interface. - -.. code-block:: none - - set firewall options interface pppoe0 adjust-mss6 '1280' - set firewall options interface wg02 adjust-mss6 '1280' - - - -.. hint:: When doing your byte calculations, you might find useful this - `Visual packet size calculator `_. diff --git a/docs/services/dynamic-dns.rst b/docs/services/dynamic-dns.rst deleted file mode 100644 index 3d802d29..00000000 --- a/docs/services/dynamic-dns.rst +++ /dev/null @@ -1,164 +0,0 @@ -.. _dynamic-dns: - -########### -Dynamic DNS -########### - -VyOS is able to update a remote DNS record when an interface gets a new IP -address. In order to do so, VyOS includes ddclient_, a Perl script written for -this only one purpose. - -ddclient_ uses two methods to update a DNS record. The first one will send -updates directly to the DNS daemon, in compliance with :rfc:`2136`. The second -one involves a third party service, like DynDNS.com or any other similar -website. This method uses HTTP requests to transmit the new IP address. You -can configure both in VyOS. - -Configuration -============= - -:rfc:`2136` Based ------------------ - -.. cfgcmd:: set service dns dynamic interface rfc2136 - - Create new :rfc:`2136` DNS update configuration which will update the IP - address assigned to `` on the service you configured under - ``. - -.. cfgcmd:: set service dns dynamic interface rfc2136 key - - File identified by `` containing the secret RNDC key shared with - remote DNS server. - -.. cfgcmd:: set service dns dynamic interface rfc2136 server - - Configure the DNS `` IP/FQDN used when updating this dynamic - assignment. - -.. cfgcmd:: set service dns dynamic interface rfc2136 zone - - Configure DNS `` to be updated. - -.. cfgcmd:: set service dns dynamic interface rfc2136 record - - Configure DNS `` which should be updated. This can be set multiple - times. - -.. cfgcmd:: set service dns dynamic interface rfc2136 ttl - - Configure optional TTL value on the given resource record. This defualts to - 600 seconds. - -Example -^^^^^^^ - -* Register DNS record ``example.vyos.io`` on DNS server ``ns1.vyos.io`` -* Use auth key file at ``/config/auth/my.key`` -* Set TTL to 300 seconds - -.. code-block:: none - - vyos@vyos# show service dns dynamic - interface eth0.7 { - rfc2136 VyOS-DNS { - key /config/auth/my.key - record example.vyos.io - server ns1.vyos.io - ttl 300 - zone vyos.io - } - } - -This will render the following ddclient_ configuration entry: - -.. code-block:: none - - # - # ddclient configuration for interface "eth0.7": - # - use=if, if=eth0.7 - - # RFC2136 dynamic DNS configuration for example.vyos.io.vyos.io - server=ns1.vyos.io - protocol=nsupdate - password=/config/auth/my.key - ttl=300 - zone=vyos.io - example.vyos.io - -.. note:: You can also keep different DNS zone updated. Just create a new - config node: ``set service dns dynamic interface rfc2136 - `` - -HTTP based services -------------------- - -VyOS is also able to use any service relying on protocols supported by ddclient. - -To use such a service, one must define a login, password, one or multiple -hostnames, protocol and server. - -.. cfgcmd:: set service dns dynamic interface service host-name - - Setup the dynamic DNS hostname `` associated with the DynDNS - provider identified by `` when the IP address on interface - `` changes. - -.. cfgcmd:: set service dns dynamic interface service login - - Configure `` used when authenticating the update request for - DynDNS service identified by ``. - For Namecheap, set the you wish to update. - -.. cfgcmd:: set service dns dynamic interface service password - - Configure `` used when authenticating the update request for - DynDNS service identified by ``. - -.. cfgcmd:: set service dns dynamic interface service protocol - - When a ``custom`` DynDNS provider is used the protocol used for communicating - to the provider must be specified under ``. See the embedded - completion helper for available protocols. - -.. cfgcmd:: set service dns dynamic interface service server - - When a ``custom`` DynDNS provider is used the `` where update - requests are being sent to must be specified. - -Example: -^^^^^^^^ - -Use DynDNS as your preferred provider: - -.. code-block:: none - - set service dns dynamic interface eth0 service dyndns - set service dns dynamic interface eth0 service dyndns login my-login - set service dns dynamic interface eth0 service dyndns password my-password - set service dns dynamic interface eth0 service dyndns host-name my-dyndns-hostname - -.. note:: Multiple services can be used per interface. Just specify as many - serives per interface as you like! - -Running Behind NAT ------------------- - -By default, ddclient_ will update a dynamic dns record using the IP address -directly attached to the interface. If your VyOS instance is behind NAT, your -record will be updated to point to your internal IP. - -ddclient_ has another way to determine the WAN IP address. This is controlled -by: - -.. cfgcmd:: set service dns dynamic interface use-web url - - Use configured `` to determine your IP address. ddclient_ will load - `` and tries to extract your IP address from the response. - -.. cfgcmd:: set service dns dynamic interface use-web skip - - ddclient_ will skip any address located before the string set in ``. - -.. _ddclient: https://github.com/ddclient/ddclient diff --git a/docs/services/index.rst b/docs/services/index.rst deleted file mode 100644 index 76520b52..00000000 --- a/docs/services/index.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _services: - -######## -Services -######## - -This chapter describes the available system/network services provided by VyOS. - -.. toctree:: - :maxdepth: 1 - - conntrack - console-server - dhcp - dns-forwarding - dynamic-dns - lldp - mdns-repeater - ipoe-server - pppoe-server - udp-broadcast-relay - router-advert - snmp - ssh - tftp - webproxy From b1cb71c71935ad6b0a7d9effe8f4dc4467de2175 Mon Sep 17 00:00:00 2001 From: rebortg Date: Mon, 30 Nov 2020 21:15:16 +0100 Subject: [PATCH 22/28] arrange: system configration --- docs/automation/index.rst | 3 +- docs/configuration/system/acceleration.rst | 7 ++++ .../system/config-management.rst | 2 ++ docs/configuration/system/conntrack.rst | 2 ++ .../system/console.rst} | 0 .../system/default-route.rst | 0 docs/configuration/system/domain-name.rst | 2 ++ docs/configuration/system/domain-search.rst | 2 ++ .../system/eventhandler.rst | 0 .../system/flow-accounting.rst | 0 .../system/host-name.rst} | 0 docs/configuration/system/index.rst | 32 +++++++++++++++++++ docs/configuration/system/ip.rst | 2 ++ docs/configuration/system/ipv6.rst | 2 ++ docs/{ => configuration}/system/lcd.rst | 0 .../system/login.rst} | 0 .../system/name-server.rst} | 0 .../system/name-servers-dhcp.rst | 2 ++ docs/{ => configuration}/system/ntp.rst | 0 docs/{ => configuration}/system/option.rst | 0 docs/{ => configuration}/system/proxy.rst | 0 .../system/static-host-mapping.rst | 2 ++ docs/configuration/system/sysctl.rst | 2 ++ docs/{ => configuration}/system/syslog.rst | 0 .../system/task-scheduler.rst | 0 docs/{ => configuration}/system/time-zone.rst | 0 .../system/wifi-requlatory-domain.rst | 2 ++ docs/index.rst | 8 +++-- docs/{system => operation}/boot-options.rst | 0 docs/{ => operation}/information.rst | 0 docs/system/advanced-index.rst | 19 ----------- docs/system/basic-index.rst | 14 -------- 32 files changed, 65 insertions(+), 38 deletions(-) create mode 100644 docs/configuration/system/acceleration.rst create mode 100644 docs/configuration/system/config-management.rst create mode 100644 docs/configuration/system/conntrack.rst rename docs/{system/serial-console.rst => configuration/system/console.rst} (100%) rename docs/{ => configuration}/system/default-route.rst (100%) create mode 100644 docs/configuration/system/domain-name.rst create mode 100644 docs/configuration/system/domain-search.rst rename docs/{ => configuration}/system/eventhandler.rst (100%) rename docs/{ => configuration}/system/flow-accounting.rst (100%) rename docs/{system/host-information.rst => configuration/system/host-name.rst} (100%) create mode 100644 docs/configuration/system/index.rst create mode 100644 docs/configuration/system/ip.rst create mode 100644 docs/configuration/system/ipv6.rst rename docs/{ => configuration}/system/lcd.rst (100%) rename docs/{system/user-management.rst => configuration/system/login.rst} (100%) rename docs/{system/system-dns.rst => configuration/system/name-server.rst} (100%) create mode 100644 docs/configuration/system/name-servers-dhcp.rst rename docs/{ => configuration}/system/ntp.rst (100%) rename docs/{ => configuration}/system/option.rst (100%) rename docs/{ => configuration}/system/proxy.rst (100%) create mode 100644 docs/configuration/system/static-host-mapping.rst create mode 100644 docs/configuration/system/sysctl.rst rename docs/{ => configuration}/system/syslog.rst (100%) rename docs/{ => configuration}/system/task-scheduler.rst (100%) rename docs/{ => configuration}/system/time-zone.rst (100%) create mode 100644 docs/configuration/system/wifi-requlatory-domain.rst rename docs/{system => operation}/boot-options.rst (100%) rename docs/{ => operation}/information.rst (100%) delete mode 100644 docs/system/advanced-index.rst delete mode 100644 docs/system/basic-index.rst diff --git a/docs/automation/index.rst b/docs/automation/index.rst index 1f2b40b1..e07dfecc 100644 --- a/docs/automation/index.rst +++ b/docs/automation/index.rst @@ -12,5 +12,4 @@ VyOS Automation .. toctree:: :maxdepth: 1 - command-scripting - http-api \ No newline at end of file + command-scripting \ No newline at end of file diff --git a/docs/configuration/system/acceleration.rst b/docs/configuration/system/acceleration.rst new file mode 100644 index 00000000..b09da38b --- /dev/null +++ b/docs/configuration/system/acceleration.rst @@ -0,0 +1,7 @@ +.. _acceleration: + +############ +Acceleration +############ + + diff --git a/docs/configuration/system/config-management.rst b/docs/configuration/system/config-management.rst new file mode 100644 index 00000000..40973713 --- /dev/null +++ b/docs/configuration/system/config-management.rst @@ -0,0 +1,2 @@ +config-management +################# \ No newline at end of file diff --git a/docs/configuration/system/conntrack.rst b/docs/configuration/system/conntrack.rst new file mode 100644 index 00000000..7d5d4308 --- /dev/null +++ b/docs/configuration/system/conntrack.rst @@ -0,0 +1,2 @@ +conntrack +######### \ No newline at end of file diff --git a/docs/system/serial-console.rst b/docs/configuration/system/console.rst similarity index 100% rename from docs/system/serial-console.rst rename to docs/configuration/system/console.rst diff --git a/docs/system/default-route.rst b/docs/configuration/system/default-route.rst similarity index 100% rename from docs/system/default-route.rst rename to docs/configuration/system/default-route.rst diff --git a/docs/configuration/system/domain-name.rst b/docs/configuration/system/domain-name.rst new file mode 100644 index 00000000..9028b65b --- /dev/null +++ b/docs/configuration/system/domain-name.rst @@ -0,0 +1,2 @@ +domain-name +########### \ No newline at end of file diff --git a/docs/configuration/system/domain-search.rst b/docs/configuration/system/domain-search.rst new file mode 100644 index 00000000..f4aef62e --- /dev/null +++ b/docs/configuration/system/domain-search.rst @@ -0,0 +1,2 @@ +domain-search +############# \ No newline at end of file diff --git a/docs/system/eventhandler.rst b/docs/configuration/system/eventhandler.rst similarity index 100% rename from docs/system/eventhandler.rst rename to docs/configuration/system/eventhandler.rst diff --git a/docs/system/flow-accounting.rst b/docs/configuration/system/flow-accounting.rst similarity index 100% rename from docs/system/flow-accounting.rst rename to docs/configuration/system/flow-accounting.rst diff --git a/docs/system/host-information.rst b/docs/configuration/system/host-name.rst similarity index 100% rename from docs/system/host-information.rst rename to docs/configuration/system/host-name.rst diff --git a/docs/configuration/system/index.rst b/docs/configuration/system/index.rst new file mode 100644 index 00000000..ecf09a64 --- /dev/null +++ b/docs/configuration/system/index.rst @@ -0,0 +1,32 @@ +###### +System +###### + + +.. toctree:: + :maxdepth: 1 + :includehidden: + + acceleration + config-management + conntrack + console + domain-name + domain-search + flow-accounting + host-name + ip + ipv6 + lcd + login + name-server + name-servers-dhcp + ntp + options + proxy + static-host-mapping + sysctl + syslog + task-scheduler + time-zone + wifi-requlatory-domain diff --git a/docs/configuration/system/ip.rst b/docs/configuration/system/ip.rst new file mode 100644 index 00000000..74116eb0 --- /dev/null +++ b/docs/configuration/system/ip.rst @@ -0,0 +1,2 @@ +ip +## \ No newline at end of file diff --git a/docs/configuration/system/ipv6.rst b/docs/configuration/system/ipv6.rst new file mode 100644 index 00000000..19ed6d62 --- /dev/null +++ b/docs/configuration/system/ipv6.rst @@ -0,0 +1,2 @@ +ipv6 +#### \ No newline at end of file diff --git a/docs/system/lcd.rst b/docs/configuration/system/lcd.rst similarity index 100% rename from docs/system/lcd.rst rename to docs/configuration/system/lcd.rst diff --git a/docs/system/user-management.rst b/docs/configuration/system/login.rst similarity index 100% rename from docs/system/user-management.rst rename to docs/configuration/system/login.rst diff --git a/docs/system/system-dns.rst b/docs/configuration/system/name-server.rst similarity index 100% rename from docs/system/system-dns.rst rename to docs/configuration/system/name-server.rst diff --git a/docs/configuration/system/name-servers-dhcp.rst b/docs/configuration/system/name-servers-dhcp.rst new file mode 100644 index 00000000..6719fef9 --- /dev/null +++ b/docs/configuration/system/name-servers-dhcp.rst @@ -0,0 +1,2 @@ +name-servers-dhcp +################# \ No newline at end of file diff --git a/docs/system/ntp.rst b/docs/configuration/system/ntp.rst similarity index 100% rename from docs/system/ntp.rst rename to docs/configuration/system/ntp.rst diff --git a/docs/system/option.rst b/docs/configuration/system/option.rst similarity index 100% rename from docs/system/option.rst rename to docs/configuration/system/option.rst diff --git a/docs/system/proxy.rst b/docs/configuration/system/proxy.rst similarity index 100% rename from docs/system/proxy.rst rename to docs/configuration/system/proxy.rst diff --git a/docs/configuration/system/static-host-mapping.rst b/docs/configuration/system/static-host-mapping.rst new file mode 100644 index 00000000..97d9a443 --- /dev/null +++ b/docs/configuration/system/static-host-mapping.rst @@ -0,0 +1,2 @@ +static-host-mapping +################### \ No newline at end of file diff --git a/docs/configuration/system/sysctl.rst b/docs/configuration/system/sysctl.rst new file mode 100644 index 00000000..82ffd159 --- /dev/null +++ b/docs/configuration/system/sysctl.rst @@ -0,0 +1,2 @@ +sysctl +###### \ No newline at end of file diff --git a/docs/system/syslog.rst b/docs/configuration/system/syslog.rst similarity index 100% rename from docs/system/syslog.rst rename to docs/configuration/system/syslog.rst diff --git a/docs/system/task-scheduler.rst b/docs/configuration/system/task-scheduler.rst similarity index 100% rename from docs/system/task-scheduler.rst rename to docs/configuration/system/task-scheduler.rst diff --git a/docs/system/time-zone.rst b/docs/configuration/system/time-zone.rst similarity index 100% rename from docs/system/time-zone.rst rename to docs/configuration/system/time-zone.rst diff --git a/docs/configuration/system/wifi-requlatory-domain.rst b/docs/configuration/system/wifi-requlatory-domain.rst new file mode 100644 index 00000000..2b6ce7d4 --- /dev/null +++ b/docs/configuration/system/wifi-requlatory-domain.rst @@ -0,0 +1,2 @@ +wifi-requlatory-domain +###################### \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 4612d5f8..96272fff 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,16 +4,17 @@ VyOS User Guide ############### - .. toctree:: :maxdepth: 2 :hidden: + :caption: FIND CAPTION NAME introducing/about introducing/history introducing/releases changelog/index + .. toctree:: :maxdepth: 2 :hidden: @@ -21,9 +22,8 @@ VyOS User Guide :caption: first steps installation/index - quick-start + quickstart/index cli - .. toctree:: :maxdepth: 2 @@ -31,6 +31,7 @@ VyOS User Guide :includehidden: :caption: Adminguide + configuration/index operation/index automation/index @@ -44,5 +45,6 @@ VyOS User Guide :includehidden: :caption: Contributing + contributing/index copyright diff --git a/docs/system/boot-options.rst b/docs/operation/boot-options.rst similarity index 100% rename from docs/system/boot-options.rst rename to docs/operation/boot-options.rst diff --git a/docs/information.rst b/docs/operation/information.rst similarity index 100% rename from docs/information.rst rename to docs/operation/information.rst diff --git a/docs/system/advanced-index.rst b/docs/system/advanced-index.rst deleted file mode 100644 index 8e855789..00000000 --- a/docs/system/advanced-index.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _advanced_system_tweaks: - -###### -System -###### - -.. toctree:: - :maxdepth: 2 - - boot-options - eventhandler - flow-accounting - lcd - ntp - option - proxy - serial-console - syslog - task-scheduler diff --git a/docs/system/basic-index.rst b/docs/system/basic-index.rst deleted file mode 100644 index b7bbf1c5..00000000 --- a/docs/system/basic-index.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _basic_system_tweaks: - -################### -Basic System Tweaks -################### - -.. toctree:: - :maxdepth: 2 - - user-management - host-information - default-route - time-zone - system-dns From ce090a4ced7fccce3fdc70142e22fa0009fae12b Mon Sep 17 00:00:00 2001 From: rebortg Date: Sun, 6 Dec 2020 21:41:10 +0100 Subject: [PATCH 23/28] arrange examples --- .../common-references.txt} | 0 docs/_include/interface-vlan-8021ad.txt | 2 +- docs/_include/interface-vlan-8021q.txt | 2 +- docs/cli.rst | 733 ++++++++++++++++++ docs/command-list-configuration.rst | 7 - docs/command-list-operation.rst | 7 - .../azure-vpn-bgp.rst | 0 .../azure-vpn-dual-bgp.rst | 0 .../bgp-ipv6-unnumbered.rst | 0 .../dhcp-relay-through-gre-bridge.rst | 0 .../examples => configexamples}/ha.rst | 0 .../examples => configexamples}/index.rst | 0 .../ospf-unnumbered.rst | 0 .../tunnelbroker-ipv6.rst | 0 .../wan-load-balancing.rst | 0 .../zone-policy.rst | 0 docs/configuration-overview.rst | 730 ----------------- docs/configuration/interfaces/openvpn.rst | 2 +- docs/configuration/nat/index.rst | 2 +- docs/configuration/policy/index.rst | 2 +- docs/configuration/service/ipoe-server.rst | 2 +- docs/configuration/service/pppoe-server.rst | 2 +- docs/configuration/system/lcd.rst | 2 +- docs/{ => configuration}/vpn/dmvpn.rst | 2 +- docs/configuration/vpn/index.rst | 15 + docs/{ => configuration}/vpn/ipsec.rst | 0 docs/{ => configuration}/vpn/l2tp.rst | 0 docs/{ => configuration}/vpn/openconnect.rst | 0 docs/{ => configuration}/vpn/pptp.rst | 0 .../vpn/site2site_ipsec.rst | 2 +- docs/{ => configuration}/vpn/sstp.rst | 2 +- docs/{vrf.rst => configuration/vrf/index.rst} | 2 +- docs/configuration/zonepolicy/index.rst | 8 + docs/contributing/debugging.rst | 2 +- docs/contributing/development.rst | 2 +- docs/contributing/documentation.rst | 2 +- docs/contributing/issues-features.rst | 2 +- docs/coverage.rst | 2 - docs/index.rst | 3 +- docs/installation/{upate.rst => update.rst} | 0 docs/operation/index.rst | 3 +- docs/vpn/index.rst | 18 - 42 files changed, 776 insertions(+), 782 deletions(-) rename docs/{common-references.rst => _include/common-references.txt} (100%) delete mode 100644 docs/command-list-configuration.rst delete mode 100644 docs/command-list-operation.rst rename docs/{appendix/examples => configexamples}/azure-vpn-bgp.rst (100%) rename docs/{appendix/examples => configexamples}/azure-vpn-dual-bgp.rst (100%) rename docs/{appendix/examples => configexamples}/bgp-ipv6-unnumbered.rst (100%) rename docs/{appendix/examples => configexamples}/dhcp-relay-through-gre-bridge.rst (100%) rename docs/{appendix/examples => configexamples}/ha.rst (100%) rename docs/{appendix/examples => configexamples}/index.rst (100%) rename docs/{appendix/examples => configexamples}/ospf-unnumbered.rst (100%) rename docs/{appendix/examples => configexamples}/tunnelbroker-ipv6.rst (100%) rename docs/{appendix/examples => configexamples}/wan-load-balancing.rst (100%) rename docs/{appendix/examples => configexamples}/zone-policy.rst (100%) delete mode 100644 docs/configuration-overview.rst rename docs/{ => configuration}/vpn/dmvpn.rst (99%) create mode 100644 docs/configuration/vpn/index.rst rename docs/{ => configuration}/vpn/ipsec.rst (100%) rename docs/{ => configuration}/vpn/l2tp.rst (100%) rename docs/{ => configuration}/vpn/openconnect.rst (100%) rename docs/{ => configuration}/vpn/pptp.rst (100%) rename docs/{ => configuration}/vpn/site2site_ipsec.rst (99%) rename docs/{ => configuration}/vpn/sstp.rst (99%) rename docs/{vrf.rst => configuration/vrf/index.rst} (99%) create mode 100644 docs/configuration/zonepolicy/index.rst rename docs/installation/{upate.rst => update.rst} (100%) delete mode 100644 docs/vpn/index.rst diff --git a/docs/common-references.rst b/docs/_include/common-references.txt similarity index 100% rename from docs/common-references.rst rename to docs/_include/common-references.txt diff --git a/docs/_include/interface-vlan-8021ad.txt b/docs/_include/interface-vlan-8021ad.txt index 12925ad4..74bc2080 100644 --- a/docs/_include/interface-vlan-8021ad.txt +++ b/docs/_include/interface-vlan-8021ad.txt @@ -140,4 +140,4 @@ tag is the one closer/closest to the Ethernet header, its name is S-TAG :var6: :var7: 20 -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/_include/interface-vlan-8021q.txt b/docs/_include/interface-vlan-8021q.txt index 37f652f3..db22a1ce 100644 --- a/docs/_include/interface-vlan-8021q.txt +++ b/docs/_include/interface-vlan-8021q.txt @@ -108,4 +108,4 @@ term used for this is ``vif``. :var3: :var4: 10 -.. include:: /common-references.rst \ No newline at end of file +.. include:: /_include/common-references.txt \ No newline at end of file diff --git a/docs/cli.rst b/docs/cli.rst index b138b18b..34ab3df6 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -97,3 +97,736 @@ To enter configuration mode use the ``configure`` command: See the configuration section of this document for more information on configuration mode. + + +.. _configuration-overview: + +###################### +Configuration Overview +###################### + +VyOS makes use of a unified configuration file for the entire system's +configuration: ``/config/config.boot``. This allows easy template +creation, backup, and replication of system configuration. A system can +thus also be easily cloned by simply copying the required configuration +files. + +Terminology +=========== +live +A VyOS system has three major types of configurations: + +* **Active** or **running configuration** is the system configuration + that is loaded and currently active (used by VyOS). Any change in + the configuration will have to be committed to belong to the + active/running configuration. + +* **Working configuration** is the one that is currently being modified + in configuration mode. Changes made to the working configuration do + not go into effect until the changes are committed with the + :cfgcmd:`commit` command. At which time the working configuration will + become the active or running configuration. + +* **Saved configuration** is the one saved to a file using the + :cfgcmd:`save` command. It allows you to keep safe a configuration for + future uses. There can be multiple configuration files. The default or + "boot" configuration is saved and loaded from the file + ``/config/config.boot``. + +Seeing and navigating the configuration +======================================= + +.. opcmd:: show configuration + + View the current active configuration, also known as the running + configuration, from the operational mode. + + .. code-block:: none + + vyos@vyos:~$ show configuration + interfaces { + ethernet eth0 { + address dhcp + hw-id 00:53:00:00:aa:01 + } + loopback lo { + } + } + service { + ssh { + port 22 + } + } + system { + config-management { + commit-revisions 20 + } + console { + device ttyS0 { + speed 9600 + } + } + login { + user vyos { + authentication { + encrypted-password **************** + } + level admin + } + } + ntp { + server 0.pool.ntp.org { + } + server 1.pool.ntp.org { + } + server 2.pool.ntp.org { + } + } + syslog { + global { + facility all { + level notice + } + facility protocols { + level debug + } + } + } + } + +By default, the configuration is displayed in a hierarchy like the above +example, this is only one of the possible ways to display the +configuration. When the configuration is generated and the device is +configured, changes are added through a collection of :cfgcmd:`set` and +:cfgcmd:`delete` commands. + +.. opcmd:: show configuration commands + + Get a collection of all the set commands required which led to the + running configuration. + + .. code-block:: none + + vyos@vyos:~$ show configuration commands + set interfaces ethernet eth0 address 'dhcp' + set interfaces ethernet eth0 hw-id '00:53:dd:44:3b:0f' + set interfaces loopback 'lo' + set service ssh port '22' + set system config-management commit-revisions '20' + set system console device ttyS0 speed '9600' + set system login user vyos authentication encrypted-password '$6$Vt68...QzF0' + set system login user vyos level 'admin' + set system ntp server '0.pool.ntp.org' + set system ntp server '1.pool.ntp.org' + set system ntp server '2.pool.ntp.org' + set system syslog global facility all level 'notice' + set system syslog global facility protocols level 'debug' + +Both these ``show`` commands should be executed when in operational +mode, they do not work directly in configuration mode. There is a +special way on how to :ref:`run_opmode_from_config_mode`. + +.. hint:: Use the ``show configuration commands | strip-private`` + command when you want to hide private data. You may want to do so if + you want to share your configuration on the `forum`_. + +.. _`forum`: https://forum.vyos.io + + +The config mode +--------------- + +When entering the configuration mode you are navigating inside a tree +structure, to enter configuration mode enter the command +:opcmd:`configure` when in operational mode. + +.. code-block:: none + + vyos@vyos$ configure + [edit] + vyos@vyos# + + +.. note:: When going into configuration mode, prompt changes from + ``$`` to ``#``. + + +All commands executed here are relative to the configuration level you +have entered. You can do everything from the top level, but commands +will be quite lengthy when manually typing them. + +The current hierarchy level can be changed by the :cfgcmd:`edit` +command. + +.. code-block:: none + + [edit] + vyos@vyos# edit interfaces ethernet eth0 + + [edit interfaces ethernet eth0] + vyos@vyos# + +You are now in a sublevel relative to ``interfaces ethernet eth0``, all +commands executed from this point on are relative to this sublevel. Use +eithe the :cfgcmd:`top` or :cfgcmd:`exit` command to go back to the top +of the hierarchy. You can also use the :cfgcmd:`up` command to move only +one level up at a time. + +.. cfgcmd:: show + +The :cfgcmd:`show` command within configuration mode will show the +working configuration indicating line changes with ``+`` for additions, +``>`` for replacements and ``-`` for deletions. + +**Example:** + +.. code-block:: none + + vyos@vyos:~$ configure + [edit] + vyos@vyos# show interfaces + ethernet eth0 { + description MY_OLD_DESCRIPTION + disable + hw-id 00:53:dd:44:3b:03 + } + loopback lo { + } + [edit] + vyos@vyos# set interfaces ethernet eth0 address dhcp + [edit] + vyos@vyos# set interfaces ethernet eth0 description MY_NEW_DESCRIPTION + [edit] + vyos@vyos# delete interfaces ethernet eth0 disable + [edit] + vyos@vyos# show interfaces + ethernet eth0 { + + address dhcp + > description MY_NEW_DESCRIPTION + - disable + hw-id 00:53:dd:44:3b:03 + } + loopback lo { + } + +It is also possible to display all `set` commands within configuration +mode using :cfgcmd:`show | commands` + +.. code-block:: none + + vyos@vyos# show interfaces ethernet eth0 | commands + set address dhcp + set hw-id 00:53:ad:44:3b:03 + +These commands are also relative to the level you are inside and only +relevant configuration blocks will be displayed when entering a +sub-level. + +.. code-block:: none + + [edit interfaces ethernet eth0] + vyos@vyos# show + address dhcp + hw-id 00:53:ad:44:3b:03 + +Exiting from the configuration mode is done via the :cfgcmd:`exit` +command from the top level, executing :cfgcmd:`exit` from within a +sub-level takes you back to the top level. + +.. code-block:: none + + [edit interfaces ethernet eth0] + vyos@vyos# exit + [edit] + vyos@vyos# exit + Warning: configuration changes have not been saved. + + +Editing the configuration +========================= + +The configuration can be edited by the use of :cfgcmd:`set` and +:cfgcmd:`delete` commands from within configuration mode. + +.. cfgcmd:: set + + Use this command to set the value of a parameter or to create a new + element. + +Configuration commands are flattened from the tree into 'one-liner' +commands shown in :opcmd:`show configuration commands` from operation +mode. Commands are relative to the level where they are executed and all +redundant information from the current level is removed from the command +entered. + +.. code-block:: none + + [edit] + vyos@vyos# set interface ethernet eth0 address 192.0.2.100/24 + + +.. code-block:: none + + [edit interfaces ethernet eth0] + vyos@vyos# set address 203.0.113.6/24 + + +These two commands above are essentially the same, just executed from +different levels in the hierarchy. + +.. cfgcmd:: delete + + To delete a configuration entry use the :cfgcmd:`delete` command, + this also deletes all sub-levels under the current level you've + specified in the :cfgcmd:`delete` command. Deleting an entry will + also result in the element reverting back to its default value if one + exists. + + .. code-block:: none + + [edit interfaces ethernet eth0] + vyos@vyos# delete address 192.0.2.100/24 + +.. cfgcmd:: commit + + Any change you do on the configuration, will not take effect until + committed using the :cfgcmd:`commit` command in configuration mode. + + .. code-block:: none + + vyos@vyos# commit + [edit] + vyos@vyos# exit + Warning: configuration changes have not been saved. + vyos@vyos:~$ + +.. _save: + +.. cfgcmd:: save + + Use this command to preserve configuration changes upon reboot. By + default it is stored at */config/config.boot*. In the case you want + to store the configuration file somewhere else, you can add a local + path, an SCP address, an FTP address or a TFTP address. + + .. code-block:: none + + vyos@vyos# save + Saving configuration to '/config/config.boot'... + Done + + .. code-block:: none + + vyos@vyos# save [tab] + Possible completions: + Save to system config file + Save to file on local machine + scp://:@:/ Save to file on remote machine + ftp://:@/ Save to file on remote machine + tftp:/// Save to file on remote machine + vyos@vyos# save tftp://192.168.0.100/vyos-test.config.boot + Saving configuration to 'tftp://192.168.0.100/vyos-test.config.boot'... + ######################################################################## 100.0% + Done + +.. cfgcmd:: exit [discard] + + Configuration mode can not be exited while uncommitted changes exist. + To exit configuration mode without applying changes, the + :cfgcmd:`exit discard` command must be used. + + All changes in the working config will thus be lost. + + .. code-block:: none + + vyos@vyos# exit + Cannot exit: configuration modified. + Use 'exit discard' to discard the changes and exit. + [edit] + vyos@vyos# exit discard + + +.. cfgcmd:: commit-confirm + + Use this command to temporarily commit your changes and set the + number of minutes available for validation. ``confirm`` must + be entered within those minutes, otherwise the system will reboot + into the previous configuration. The default value is 10 minutes. + + + What if you are doing something dangerous? Suppose you want to setup + a firewall, and you are not sure there are no mistakes that will lock + you out of your system. You can use confirmed commit. If you issue + the ``commit-confirm`` command, your changes will be commited, and if + you don't issue issue the ``confirm`` command in 10 minutes, your + system will reboot into previous config revision. + + .. code-block:: none + + vyos@router# set interfaces ethernet eth0 firewall local name FromWorld + vyos@router# commit-confirm + commit confirm will be automatically reboot in 10 minutes unless confirmed + Proceed? [confirm]y + [edit] + vyos@router# confirm + [edit] + + + .. note:: A reboot because you did not enter ``confirm`` will not + take you necessarily to the *saved configuration*, but to the + point before the unfortunate commit. + + +.. cfgcmd:: copy + + Copy a configuration element. + + You can copy and remove configuration subtrees. Suppose you set up a + firewall ruleset ``FromWorld`` with one rule that allows traffic from + specific subnet. Now you want to setup a similar rule, but for + different subnet. Change your edit level to + ``firewall name FromWorld`` and use ``copy rule 10 to rule 20``, then + modify rule 20. + + + .. code-block:: none + + vyos@router# show firewall name FromWorld + default-action drop + rule 10 { + action accept + source { + address 203.0.113.0/24 + } + } + [edit] + vyos@router# edit firewall name FromWorld + [edit firewall name FromWorld] + vyos@router# copy rule 10 to rule 20 + [edit firewall name FromWorld] + vyos@router# set rule 20 source address 198.51.100.0/24 + [edit firewall name FromWorld] + vyos@router# commit + [edit firewall name FromWorld] + + +.. cfgcmd:: rename + + Rename a configuration element. + + You can also rename config subtrees: + + .. code-block:: none + + vyos@router# rename rule 10 to rule 5 + [edit firewall name FromWorld] + vyos@router# commit + [edit firewall name FromWorld] + + Note that ``show`` command respects your edit level and from this + level you can view the modified firewall ruleset with just ``show`` + with no parameters. + + .. code-block:: none + + vyos@router# show + default-action drop + rule 5 { + action accept + source { + address 203.0.113.0/24 + } + } + rule 20 { + action accept + source { + address 198.51.100.0/24 + } + } + + +.. cfgcmd:: comment "comment text" + + Add comment as an annotation to a configuration node. + + The ``comment`` command allows you to insert a comment above the + ```` configuration section. When shown, comments are + enclosed with ``/*`` and ``*/`` as open/close delimiters. Comments + need to be commited, just like other config changes. + + To remove an existing comment from your current configuration, + specify an empty string enclosed in double quote marks (``""``) as + the comment text. + + Example: + + .. code-block:: none + + vyos@vyos# comment firewall all-ping "Yes I know this VyOS is cool" + vyos@vyos# commit + vyos@vyos# show + firewall { + /* Yes I know this VyOS is cool */ + all-ping enable + broadcast-ping disable + ... + } + + .. note:: An important thing to note is that since the comment is + added on top of the section, it will not appear if the ``show +
`` command is used. With the above example, the `show + firewall` command would return starting after the ``firewall + {`` line, hiding the comment. + + + + + + +.. _run_opmode_from_config_mode: + +Access opmode from config mode +============================== + +When inside configuration mode you are not directly able to execute +operational commands. + +.. cfgcmd:: run + + Access to these commands are possible through the use of the + ``run [command]`` command. From this command you will have access to + everything accessible from operational mode. + + Command completion and syntax help with ``?`` and ``[tab]`` will also + work. + + .. code-block:: none + + [edit] + vyos@vyos# run show interfaces + Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down + Interface IP Address S/L Description + --------- ---------- --- ----------- + eth0 0.0.0.0/0 u/u + +Managing configurations +======================= + +VyOS comes with an integrated versioning system for the system +configuration. It automatically maintains a backup of every previous +configuration which has been committed to the system. The configurations +are versioned locally for rollback but they can also be stored on a +remote host for archiving/backup reasons. + +Local Archive +------------- + +Revisions are stored on disk. You can view, compare and rollback them to +any previous revisions if something goes wrong. + +.. opcmd:: show system commit + + View all existing revisions on the local system. + + .. code-block:: none + + vyos@vyos:~$ show system commit + 0 2015-03-30 08:53:03 by vyos via cli + 1 2015-03-30 08:52:20 by vyos via cli + 2 2015-03-26 21:26:01 by root via boot-config-loader + 3 2015-03-26 20:43:18 by root via boot-config-loader + 4 2015-03-25 11:06:14 by root via boot-config-loader + 5 2015-03-25 01:04:28 by root via boot-config-loader + 6 2015-03-25 00:16:47 by vyos via cli + 7 2015-03-24 23:43:45 by root via boot-config-loader + + +.. cfgcmd:: set system config-management commit-revisions + + You can specify the number of revisions stored on disk. N can be in + the range of 0 - 65535. When the number of revisions exceeds the + configured value, the oldest revision is removed. The default setting + for this value is to store 100 revisions locally. + + +Compare configurations +---------------------- + +VyOS lets you compare different configurations. + +.. cfgcmd:: compare + + Use this command to spot what the differences are between different + configurations. + + .. code-block:: none + + vyos@vyos# compare [tab] + Possible completions: + Compare working & active configurations + saved Compare working & saved configurations + Compare working with revision N + Compare revision N with M + Revisions: + 0 2013-12-17 20:01:37 root by boot-config-loader + 1 2013-12-13 15:59:31 root by boot-config-loader + 2 2013-12-12 21:56:22 vyos by cli + 3 2013-12-12 21:55:11 vyos by cli + 4 2013-12-12 21:27:54 vyos by cli + 5 2013-12-12 21:23:29 vyos by cli + 6 2013-12-12 21:13:59 root by boot-config-loader + 7 2013-12-12 16:25:19 vyos by cli + 8 2013-12-12 15:44:36 vyos by cli + 9 2013-12-12 15:42:07 root by boot-config-loader + 10 2013-12-12 15:42:06 root by init + + The command :cfgcmd:`compare` allows you to compare different type of + configurations. It also lets you compare different revisions through + the :cfgcmd:`compare N M` command, where N and M are revision + numbers. The output will describe how the configuration N is when + compared to M indicating with a plus sign (``+``) the additional + parts N has when compared to M, and indicating with a minus sign + (``-``) the lacking parts N misses when compared to M. + + .. code-block:: none + + vyos@vyos# compare 0 6 + [edit interfaces] + +dummy dum1 { + + address 10.189.0.1/31 + +} + [edit interfaces ethernet eth0] + +vif 99 { + + address 10.199.0.1/31 + +} + -vif 900 { + - address 192.0.2.4/24 + -} + + +.. opcmd:: show system commit diff + + Show commit revision difference. + + +The command above also lets you see the difference between two commits. +By default the difference with the running config is shown. + +.. code-block:: none + + vyos@router# run show system commit diff 4 + [edit system] + +ipv6 { + + disable-forwarding + +} + +This means four commits ago we did ``set system ipv6 disable-forwarding``. + + +Rollback Changes +---------------- + +You can rollback configuration changes using the rollback command. This +will apply the selected revision and trigger a system reboot. + +.. cfgcmd:: rollback + + Rollback to revision N (currently requires reboot) + + .. code-block:: none + + vyos@vyos# compare 1 + [edit system] + >host-name vyos-1 + [edit] + + vyos@vyos# rollback 1 + Proceed with reboot? [confirm][y] + Broadcast message from root@vyos-1 (pts/0) (Tue Dec 17 21:07:45 2013): + The system is going down for reboot NOW! + +Remote Archive +-------------- + +VyOS can upload the configuration to a remote location after each call +to :cfgcmd:`commit`. You will have to set the commit-archive location. +TFTP, FTP, SCP and SFTP servers are supported. Every time a +:cfgcmd:`commit` is successfull the ``config.boot`` file will be copied +to the defined destination(s). The filename used on the remote host will +be ``config.boot-hostname.YYYYMMDD_HHMMSS``. + +.. cfgcmd:: set system config-management commit-archive location + + Specify remote location of commit archive as any of the below + :abbr:`URI (Uniform Resource Identifier)` + + * ``scp://:@:/`` + * ``sftp://:@/`` + * ``ftp://:@/`` + * ``tftp:///`` + +.. note:: The number of revisions don't affect the commit-archive. + +.. note:: You may find VyOS not allowing the secure connection because + it cannot verify the legitimacy of the remote server. You can use + the workaround below to quickly add the remote host's SSH + fingerprint to your ``~/.ssh/known_hosts`` file: + + .. code-block:: none + + vyos@vyos# ssh-keyscan >> ~/.ssh/known_hosts + +Saving and loading manually +--------------------------- + +You can use the ``save`` and ``load`` commands if you want to manually +manage specific configuration files. + +When using the save_ command, you can add a specific location where +to store your configuration file. And, when needed it, you will be able +to load it with the ``load`` command: + +.. cfgcmd:: load + + Use this command to load a configuration which will replace the + running configuration. Define the location of the configuration file + to be loaded. You can use a path to a local file, an SCP address, an + SFTP address, an FTP address, an HTTP address, an HTTPS address or a + TFTP address. + + .. code-block:: none + + vyos@vyos# load + Possible completions: + Load from system config file + Load from file on local machine + scp://:@:/ Load from file on remote machine + sftp://:@/ Load from file on remote machine + ftp://:@/ Load from file on remote machine + http:/// Load from file on remote machine + https:/// Load from file on remote machine + tftp:/// Load from file on remote machine + + + +Restore Default +--------------- + +In the case you want to completely delete your configuration and restore +the default one, you can enter the following command in configuration +mode: + +.. code-block:: none + + load /opt/vyatta/etc/config.boot.default + +You will be asked if you want to continue. If you accept, you will have +to use :cfgcmd:`commit` if you want to make the changes active. + +Then you may want to :cfgcmd:`save` in order to delete the saved +configuration too. + +.. note:: If you are remotely connected, you will lose your connection. + You may want to copy first the config, edit it to ensure + connectivity, and load the edited config. + diff --git a/docs/command-list-configuration.rst b/docs/command-list-configuration.rst deleted file mode 100644 index 7b981518..00000000 --- a/docs/command-list-configuration.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _configuration_level_commands: - -******************************** -Configuration Level Command List -******************************** - -.. cfgcmdlist:: diff --git a/docs/command-list-operation.rst b/docs/command-list-operation.rst deleted file mode 100644 index bbb0298c..00000000 --- a/docs/command-list-operation.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _operational_level_commands: - -****************************** -Operational Level Command List -****************************** - -.. opcmdlist:: diff --git a/docs/appendix/examples/azure-vpn-bgp.rst b/docs/configexamples/azure-vpn-bgp.rst similarity index 100% rename from docs/appendix/examples/azure-vpn-bgp.rst rename to docs/configexamples/azure-vpn-bgp.rst diff --git a/docs/appendix/examples/azure-vpn-dual-bgp.rst b/docs/configexamples/azure-vpn-dual-bgp.rst similarity index 100% rename from docs/appendix/examples/azure-vpn-dual-bgp.rst rename to docs/configexamples/azure-vpn-dual-bgp.rst diff --git a/docs/appendix/examples/bgp-ipv6-unnumbered.rst b/docs/configexamples/bgp-ipv6-unnumbered.rst similarity index 100% rename from docs/appendix/examples/bgp-ipv6-unnumbered.rst rename to docs/configexamples/bgp-ipv6-unnumbered.rst diff --git a/docs/appendix/examples/dhcp-relay-through-gre-bridge.rst b/docs/configexamples/dhcp-relay-through-gre-bridge.rst similarity index 100% rename from docs/appendix/examples/dhcp-relay-through-gre-bridge.rst rename to docs/configexamples/dhcp-relay-through-gre-bridge.rst diff --git a/docs/appendix/examples/ha.rst b/docs/configexamples/ha.rst similarity index 100% rename from docs/appendix/examples/ha.rst rename to docs/configexamples/ha.rst diff --git a/docs/appendix/examples/index.rst b/docs/configexamples/index.rst similarity index 100% rename from docs/appendix/examples/index.rst rename to docs/configexamples/index.rst diff --git a/docs/appendix/examples/ospf-unnumbered.rst b/docs/configexamples/ospf-unnumbered.rst similarity index 100% rename from docs/appendix/examples/ospf-unnumbered.rst rename to docs/configexamples/ospf-unnumbered.rst diff --git a/docs/appendix/examples/tunnelbroker-ipv6.rst b/docs/configexamples/tunnelbroker-ipv6.rst similarity index 100% rename from docs/appendix/examples/tunnelbroker-ipv6.rst rename to docs/configexamples/tunnelbroker-ipv6.rst diff --git a/docs/appendix/examples/wan-load-balancing.rst b/docs/configexamples/wan-load-balancing.rst similarity index 100% rename from docs/appendix/examples/wan-load-balancing.rst rename to docs/configexamples/wan-load-balancing.rst diff --git a/docs/appendix/examples/zone-policy.rst b/docs/configexamples/zone-policy.rst similarity index 100% rename from docs/appendix/examples/zone-policy.rst rename to docs/configexamples/zone-policy.rst diff --git a/docs/configuration-overview.rst b/docs/configuration-overview.rst deleted file mode 100644 index 5658cdbb..00000000 --- a/docs/configuration-overview.rst +++ /dev/null @@ -1,730 +0,0 @@ -.. _configuration-overview: - -###################### -Configuration Overview -###################### - -VyOS makes use of a unified configuration file for the entire system's -configuration: ``/config/config.boot``. This allows easy template -creation, backup, and replication of system configuration. A system can -thus also be easily cloned by simply copying the required configuration -files. - -Terminology -=========== -live -A VyOS system has three major types of configurations: - -* **Active** or **running configuration** is the system configuration - that is loaded and currently active (used by VyOS). Any change in - the configuration will have to be committed to belong to the - active/running configuration. - -* **Working configuration** is the one that is currently being modified - in configuration mode. Changes made to the working configuration do - not go into effect until the changes are committed with the - :cfgcmd:`commit` command. At which time the working configuration will - become the active or running configuration. - -* **Saved configuration** is the one saved to a file using the - :cfgcmd:`save` command. It allows you to keep safe a configuration for - future uses. There can be multiple configuration files. The default or - "boot" configuration is saved and loaded from the file - ``/config/config.boot``. - -Seeing and navigating the configuration -======================================= - -.. opcmd:: show configuration - - View the current active configuration, also known as the running - configuration, from the operational mode. - - .. code-block:: none - - vyos@vyos:~$ show configuration - interfaces { - ethernet eth0 { - address dhcp - hw-id 00:53:00:00:aa:01 - } - loopback lo { - } - } - service { - ssh { - port 22 - } - } - system { - config-management { - commit-revisions 20 - } - console { - device ttyS0 { - speed 9600 - } - } - login { - user vyos { - authentication { - encrypted-password **************** - } - level admin - } - } - ntp { - server 0.pool.ntp.org { - } - server 1.pool.ntp.org { - } - server 2.pool.ntp.org { - } - } - syslog { - global { - facility all { - level notice - } - facility protocols { - level debug - } - } - } - } - -By default, the configuration is displayed in a hierarchy like the above -example, this is only one of the possible ways to display the -configuration. When the configuration is generated and the device is -configured, changes are added through a collection of :cfgcmd:`set` and -:cfgcmd:`delete` commands. - -.. opcmd:: show configuration commands - - Get a collection of all the set commands required which led to the - running configuration. - - .. code-block:: none - - vyos@vyos:~$ show configuration commands - set interfaces ethernet eth0 address 'dhcp' - set interfaces ethernet eth0 hw-id '00:53:dd:44:3b:0f' - set interfaces loopback 'lo' - set service ssh port '22' - set system config-management commit-revisions '20' - set system console device ttyS0 speed '9600' - set system login user vyos authentication encrypted-password '$6$Vt68...QzF0' - set system login user vyos level 'admin' - set system ntp server '0.pool.ntp.org' - set system ntp server '1.pool.ntp.org' - set system ntp server '2.pool.ntp.org' - set system syslog global facility all level 'notice' - set system syslog global facility protocols level 'debug' - -Both these ``show`` commands should be executed when in operational -mode, they do not work directly in configuration mode. There is a -special way on how to :ref:`run_opmode_from_config_mode`. - -.. hint:: Use the ``show configuration commands | strip-private`` - command when you want to hide private data. You may want to do so if - you want to share your configuration on the `forum`_. - -.. _`forum`: https://forum.vyos.io - - -The config mode ---------------- - -When entering the configuration mode you are navigating inside a tree -structure, to enter configuration mode enter the command -:opcmd:`configure` when in operational mode. - -.. code-block:: none - - vyos@vyos$ configure - [edit] - vyos@vyos# - - -.. note:: When going into configuration mode, prompt changes from - ``$`` to ``#``. - - -All commands executed here are relative to the configuration level you -have entered. You can do everything from the top level, but commands -will be quite lengthy when manually typing them. - -The current hierarchy level can be changed by the :cfgcmd:`edit` -command. - -.. code-block:: none - - [edit] - vyos@vyos# edit interfaces ethernet eth0 - - [edit interfaces ethernet eth0] - vyos@vyos# - -You are now in a sublevel relative to ``interfaces ethernet eth0``, all -commands executed from this point on are relative to this sublevel. Use -eithe the :cfgcmd:`top` or :cfgcmd:`exit` command to go back to the top -of the hierarchy. You can also use the :cfgcmd:`up` command to move only -one level up at a time. - -.. cfgcmd:: show - -The :cfgcmd:`show` command within configuration mode will show the -working configuration indicating line changes with ``+`` for additions, -``>`` for replacements and ``-`` for deletions. - -**Example:** - -.. code-block:: none - - vyos@vyos:~$ configure - [edit] - vyos@vyos# show interfaces - ethernet eth0 { - description MY_OLD_DESCRIPTION - disable - hw-id 00:53:dd:44:3b:03 - } - loopback lo { - } - [edit] - vyos@vyos# set interfaces ethernet eth0 address dhcp - [edit] - vyos@vyos# set interfaces ethernet eth0 description MY_NEW_DESCRIPTION - [edit] - vyos@vyos# delete interfaces ethernet eth0 disable - [edit] - vyos@vyos# show interfaces - ethernet eth0 { - + address dhcp - > description MY_NEW_DESCRIPTION - - disable - hw-id 00:53:dd:44:3b:03 - } - loopback lo { - } - -It is also possible to display all `set` commands within configuration -mode using :cfgcmd:`show | commands` - -.. code-block:: none - - vyos@vyos# show interfaces ethernet eth0 | commands - set address dhcp - set hw-id 00:53:ad:44:3b:03 - -These commands are also relative to the level you are inside and only -relevant configuration blocks will be displayed when entering a -sub-level. - -.. code-block:: none - - [edit interfaces ethernet eth0] - vyos@vyos# show - address dhcp - hw-id 00:53:ad:44:3b:03 - -Exiting from the configuration mode is done via the :cfgcmd:`exit` -command from the top level, executing :cfgcmd:`exit` from within a -sub-level takes you back to the top level. - -.. code-block:: none - - [edit interfaces ethernet eth0] - vyos@vyos# exit - [edit] - vyos@vyos# exit - Warning: configuration changes have not been saved. - - -Editing the configuration -========================= - -The configuration can be edited by the use of :cfgcmd:`set` and -:cfgcmd:`delete` commands from within configuration mode. - -.. cfgcmd:: set - - Use this command to set the value of a parameter or to create a new - element. - -Configuration commands are flattened from the tree into 'one-liner' -commands shown in :opcmd:`show configuration commands` from operation -mode. Commands are relative to the level where they are executed and all -redundant information from the current level is removed from the command -entered. - -.. code-block:: none - - [edit] - vyos@vyos# set interface ethernet eth0 address 192.0.2.100/24 - - -.. code-block:: none - - [edit interfaces ethernet eth0] - vyos@vyos# set address 203.0.113.6/24 - - -These two commands above are essentially the same, just executed from -different levels in the hierarchy. - -.. cfgcmd:: delete - - To delete a configuration entry use the :cfgcmd:`delete` command, - this also deletes all sub-levels under the current level you've - specified in the :cfgcmd:`delete` command. Deleting an entry will - also result in the element reverting back to its default value if one - exists. - - .. code-block:: none - - [edit interfaces ethernet eth0] - vyos@vyos# delete address 192.0.2.100/24 - -.. cfgcmd:: commit - - Any change you do on the configuration, will not take effect until - committed using the :cfgcmd:`commit` command in configuration mode. - - .. code-block:: none - - vyos@vyos# commit - [edit] - vyos@vyos# exit - Warning: configuration changes have not been saved. - vyos@vyos:~$ - -.. _save: - -.. cfgcmd:: save - - Use this command to preserve configuration changes upon reboot. By - default it is stored at */config/config.boot*. In the case you want - to store the configuration file somewhere else, you can add a local - path, an SCP address, an FTP address or a TFTP address. - - .. code-block:: none - - vyos@vyos# save - Saving configuration to '/config/config.boot'... - Done - - .. code-block:: none - - vyos@vyos# save [tab] - Possible completions: - Save to system config file - Save to file on local machine - scp://:@:/ Save to file on remote machine - ftp://:@/ Save to file on remote machine - tftp:/// Save to file on remote machine - vyos@vyos# save tftp://192.168.0.100/vyos-test.config.boot - Saving configuration to 'tftp://192.168.0.100/vyos-test.config.boot'... - ######################################################################## 100.0% - Done - -.. cfgcmd:: exit [discard] - - Configuration mode can not be exited while uncommitted changes exist. - To exit configuration mode without applying changes, the - :cfgcmd:`exit discard` command must be used. - - All changes in the working config will thus be lost. - - .. code-block:: none - - vyos@vyos# exit - Cannot exit: configuration modified. - Use 'exit discard' to discard the changes and exit. - [edit] - vyos@vyos# exit discard - - -.. cfgcmd:: commit-confirm - - Use this command to temporarily commit your changes and set the - number of minutes available for validation. ``confirm`` must - be entered within those minutes, otherwise the system will reboot - into the previous configuration. The default value is 10 minutes. - - - What if you are doing something dangerous? Suppose you want to setup - a firewall, and you are not sure there are no mistakes that will lock - you out of your system. You can use confirmed commit. If you issue - the ``commit-confirm`` command, your changes will be commited, and if - you don't issue issue the ``confirm`` command in 10 minutes, your - system will reboot into previous config revision. - - .. code-block:: none - - vyos@router# set interfaces ethernet eth0 firewall local name FromWorld - vyos@router# commit-confirm - commit confirm will be automatically reboot in 10 minutes unless confirmed - Proceed? [confirm]y - [edit] - vyos@router# confirm - [edit] - - - .. note:: A reboot because you did not enter ``confirm`` will not - take you necessarily to the *saved configuration*, but to the - point before the unfortunate commit. - - -.. cfgcmd:: copy - - Copy a configuration element. - - You can copy and remove configuration subtrees. Suppose you set up a - firewall ruleset ``FromWorld`` with one rule that allows traffic from - specific subnet. Now you want to setup a similar rule, but for - different subnet. Change your edit level to - ``firewall name FromWorld`` and use ``copy rule 10 to rule 20``, then - modify rule 20. - - - .. code-block:: none - - vyos@router# show firewall name FromWorld - default-action drop - rule 10 { - action accept - source { - address 203.0.113.0/24 - } - } - [edit] - vyos@router# edit firewall name FromWorld - [edit firewall name FromWorld] - vyos@router# copy rule 10 to rule 20 - [edit firewall name FromWorld] - vyos@router# set rule 20 source address 198.51.100.0/24 - [edit firewall name FromWorld] - vyos@router# commit - [edit firewall name FromWorld] - - -.. cfgcmd:: rename - - Rename a configuration element. - - You can also rename config subtrees: - - .. code-block:: none - - vyos@router# rename rule 10 to rule 5 - [edit firewall name FromWorld] - vyos@router# commit - [edit firewall name FromWorld] - - Note that ``show`` command respects your edit level and from this - level you can view the modified firewall ruleset with just ``show`` - with no parameters. - - .. code-block:: none - - vyos@router# show - default-action drop - rule 5 { - action accept - source { - address 203.0.113.0/24 - } - } - rule 20 { - action accept - source { - address 198.51.100.0/24 - } - } - - -.. cfgcmd:: comment "comment text" - - Add comment as an annotation to a configuration node. - - The ``comment`` command allows you to insert a comment above the - ```` configuration section. When shown, comments are - enclosed with ``/*`` and ``*/`` as open/close delimiters. Comments - need to be commited, just like other config changes. - - To remove an existing comment from your current configuration, - specify an empty string enclosed in double quote marks (``""``) as - the comment text. - - Example: - - .. code-block:: none - - vyos@vyos# comment firewall all-ping "Yes I know this VyOS is cool" - vyos@vyos# commit - vyos@vyos# show - firewall { - /* Yes I know this VyOS is cool */ - all-ping enable - broadcast-ping disable - ... - } - - .. note:: An important thing to note is that since the comment is - added on top of the section, it will not appear if the ``show -
`` command is used. With the above example, the `show - firewall` command would return starting after the ``firewall - {`` line, hiding the comment. - - - - - - -.. _run_opmode_from_config_mode: - -Access opmode from config mode -============================== - -When inside configuration mode you are not directly able to execute -operational commands. - -.. cfgcmd:: run - - Access to these commands are possible through the use of the - ``run [command]`` command. From this command you will have access to - everything accessible from operational mode. - - Command completion and syntax help with ``?`` and ``[tab]`` will also - work. - - .. code-block:: none - - [edit] - vyos@vyos# run show interfaces - Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down - Interface IP Address S/L Description - --------- ---------- --- ----------- - eth0 0.0.0.0/0 u/u - -Managing configurations -======================= - -VyOS comes with an integrated versioning system for the system -configuration. It automatically maintains a backup of every previous -configuration which has been committed to the system. The configurations -are versioned locally for rollback but they can also be stored on a -remote host for archiving/backup reasons. - -Local Archive -------------- - -Revisions are stored on disk. You can view, compare and rollback them to -any previous revisions if something goes wrong. - -.. opcmd:: show system commit - - View all existing revisions on the local system. - - .. code-block:: none - - vyos@vyos:~$ show system commit - 0 2015-03-30 08:53:03 by vyos via cli - 1 2015-03-30 08:52:20 by vyos via cli - 2 2015-03-26 21:26:01 by root via boot-config-loader - 3 2015-03-26 20:43:18 by root via boot-config-loader - 4 2015-03-25 11:06:14 by root via boot-config-loader - 5 2015-03-25 01:04:28 by root via boot-config-loader - 6 2015-03-25 00:16:47 by vyos via cli - 7 2015-03-24 23:43:45 by root via boot-config-loader - - -.. cfgcmd:: set system config-management commit-revisions - - You can specify the number of revisions stored on disk. N can be in - the range of 0 - 65535. When the number of revisions exceeds the - configured value, the oldest revision is removed. The default setting - for this value is to store 100 revisions locally. - - -Compare configurations ----------------------- - -VyOS lets you compare different configurations. - -.. cfgcmd:: compare - - Use this command to spot what the differences are between different - configurations. - - .. code-block:: none - - vyos@vyos# compare [tab] - Possible completions: - Compare working & active configurations - saved Compare working & saved configurations - Compare working with revision N - Compare revision N with M - Revisions: - 0 2013-12-17 20:01:37 root by boot-config-loader - 1 2013-12-13 15:59:31 root by boot-config-loader - 2 2013-12-12 21:56:22 vyos by cli - 3 2013-12-12 21:55:11 vyos by cli - 4 2013-12-12 21:27:54 vyos by cli - 5 2013-12-12 21:23:29 vyos by cli - 6 2013-12-12 21:13:59 root by boot-config-loader - 7 2013-12-12 16:25:19 vyos by cli - 8 2013-12-12 15:44:36 vyos by cli - 9 2013-12-12 15:42:07 root by boot-config-loader - 10 2013-12-12 15:42:06 root by init - - The command :cfgcmd:`compare` allows you to compare different type of - configurations. It also lets you compare different revisions through - the :cfgcmd:`compare N M` command, where N and M are revision - numbers. The output will describe how the configuration N is when - compared to M indicating with a plus sign (``+``) the additional - parts N has when compared to M, and indicating with a minus sign - (``-``) the lacking parts N misses when compared to M. - - .. code-block:: none - - vyos@vyos# compare 0 6 - [edit interfaces] - +dummy dum1 { - + address 10.189.0.1/31 - +} - [edit interfaces ethernet eth0] - +vif 99 { - + address 10.199.0.1/31 - +} - -vif 900 { - - address 192.0.2.4/24 - -} - - -.. opcmd:: show system commit diff - - Show commit revision difference. - - -The command above also lets you see the difference between two commits. -By default the difference with the running config is shown. - -.. code-block:: none - - vyos@router# run show system commit diff 4 - [edit system] - +ipv6 { - + disable-forwarding - +} - -This means four commits ago we did ``set system ipv6 disable-forwarding``. - - -Rollback Changes ----------------- - -You can rollback configuration changes using the rollback command. This -will apply the selected revision and trigger a system reboot. - -.. cfgcmd:: rollback - - Rollback to revision N (currently requires reboot) - - .. code-block:: none - - vyos@vyos# compare 1 - [edit system] - >host-name vyos-1 - [edit] - - vyos@vyos# rollback 1 - Proceed with reboot? [confirm][y] - Broadcast message from root@vyos-1 (pts/0) (Tue Dec 17 21:07:45 2013): - The system is going down for reboot NOW! - -Remote Archive --------------- - -VyOS can upload the configuration to a remote location after each call -to :cfgcmd:`commit`. You will have to set the commit-archive location. -TFTP, FTP, SCP and SFTP servers are supported. Every time a -:cfgcmd:`commit` is successfull the ``config.boot`` file will be copied -to the defined destination(s). The filename used on the remote host will -be ``config.boot-hostname.YYYYMMDD_HHMMSS``. - -.. cfgcmd:: set system config-management commit-archive location - - Specify remote location of commit archive as any of the below - :abbr:`URI (Uniform Resource Identifier)` - - * ``scp://:@:/`` - * ``sftp://:@/`` - * ``ftp://:@/`` - * ``tftp:///`` - -.. note:: The number of revisions don't affect the commit-archive. - -.. note:: You may find VyOS not allowing the secure connection because - it cannot verify the legitimacy of the remote server. You can use - the workaround below to quickly add the remote host's SSH - fingerprint to your ``~/.ssh/known_hosts`` file: - - .. code-block:: none - - vyos@vyos# ssh-keyscan >> ~/.ssh/known_hosts - -Saving and loading manually ---------------------------- - -You can use the ``save`` and ``load`` commands if you want to manually -manage specific configuration files. - -When using the save_ command, you can add a specific location where -to store your configuration file. And, when needed it, you will be able -to load it with the ``load`` command: - -.. cfgcmd:: load - - Use this command to load a configuration which will replace the - running configuration. Define the location of the configuration file - to be loaded. You can use a path to a local file, an SCP address, an - SFTP address, an FTP address, an HTTP address, an HTTPS address or a - TFTP address. - - .. code-block:: none - - vyos@vyos# load - Possible completions: - Load from system config file - Load from file on local machine - scp://:@:/ Load from file on remote machine - sftp://:@/ Load from file on remote machine - ftp://:@/ Load from file on remote machine - http:/// Load from file on remote machine - https:/// Load from file on remote machine - tftp:/// Load from file on remote machine - - - -Restore Default ---------------- - -In the case you want to completely delete your configuration and restore -the default one, you can enter the following command in configuration -mode: - -.. code-block:: none - - load /opt/vyatta/etc/config.boot.default - -You will be asked if you want to continue. If you accept, you will have -to use :cfgcmd:`commit` if you want to make the changes active. - -Then you may want to :cfgcmd:`save` in order to delete the saved -configuration too. - -.. note:: If you are remotely connected, you will lose your connection. - You may want to copy first the config, edit it to ensure - connectivity, and load the edited config. diff --git a/docs/configuration/interfaces/openvpn.rst b/docs/configuration/interfaces/openvpn.rst index 7646959c..f503ae84 100644 --- a/docs/configuration/interfaces/openvpn.rst +++ b/docs/configuration/interfaces/openvpn.rst @@ -581,4 +581,4 @@ The following commands let you reset OpenVPN. -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/configuration/nat/index.rst b/docs/configuration/nat/index.rst index 85bd41d5..5aeffb63 100644 --- a/docs/configuration/nat/index.rst +++ b/docs/configuration/nat/index.rst @@ -606,7 +606,7 @@ The ASP requests that all connections from this company should come from 172.29.41.89 - an address that is assigned by the ASP and not in use at the customer site. -.. figure:: _static/images/nat_before_vpn_topology.png +.. figure:: /_static/images/nat_before_vpn_topology.png :scale: 100 % :alt: NAT before VPN Topology diff --git a/docs/configuration/policy/index.rst b/docs/configuration/policy/index.rst index 557911d9..4b7d48ee 100644 --- a/docs/configuration/policy/index.rst +++ b/docs/configuration/policy/index.rst @@ -125,7 +125,7 @@ Routing tables that will be used in this example are: * ``main`` Routing table used by VyOS and other interfaces not participating in PBR -.. figure:: ../_static/images/pbr_example_1.png +.. figure:: /_static/images/pbr_example_1.png :scale: 80 % :alt: PBR multiple uplinks diff --git a/docs/configuration/service/ipoe-server.rst b/docs/configuration/service/ipoe-server.rst index 279f0c6d..3f794af8 100644 --- a/docs/configuration/service/ipoe-server.rst +++ b/docs/configuration/service/ipoe-server.rst @@ -146,4 +146,4 @@ The rate-limit is set in kbit/sec. -------+------------+-------------------+-------------+-----+--------+------------+--------+----------+------------------ ipoe0 | eth2 | 08:00:27:2f:d8:06 | 192.168.0.2 | | | 500/500 | active | 00:00:05 | dccc870fd31349fb -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/configuration/service/pppoe-server.rst b/docs/configuration/service/pppoe-server.rst index 4deb6c7e..28d1f097 100644 --- a/docs/configuration/service/pppoe-server.rst +++ b/docs/configuration/service/pppoe-server.rst @@ -394,4 +394,4 @@ a /56 subnet for the clients internal use. --------+----------+-------------+--------------------------+---------------------+-------------------+------------+--------+----------+----------+---------- ppp0 | test | 192.168.0.1 | 2001:db8:8002:0:200::/64 | 2001:db8:8003::1/56 | 00:53:00:12:42:eb | | active | 00:00:49 | 875 B | 2.1 KiB -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/configuration/system/lcd.rst b/docs/configuration/system/lcd.rst index 2509946e..808d45a2 100644 --- a/docs/configuration/system/lcd.rst +++ b/docs/configuration/system/lcd.rst @@ -41,5 +41,5 @@ Configuration .. note:: We can't support all displays from the beginning. If your display type is missing, please create a feature request via Phabricator_. -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/vpn/dmvpn.rst b/docs/configuration/vpn/dmvpn.rst similarity index 99% rename from docs/vpn/dmvpn.rst rename to docs/configuration/vpn/dmvpn.rst index 5100b92f..d6706421 100644 --- a/docs/vpn/dmvpn.rst +++ b/docs/configuration/vpn/dmvpn.rst @@ -26,7 +26,7 @@ peers. complete solution also incorporates the use of a routing protocol. BGP is particularly well suited for use with DMVPN. -.. figure:: ../_static/images/vpn_dmvpn_topology01.png +.. figure:: /_static/images/vpn_dmvpn_topology01.png :scale: 40 % :alt: Baseline DMVPN topology diff --git a/docs/configuration/vpn/index.rst b/docs/configuration/vpn/index.rst new file mode 100644 index 00000000..397093c2 --- /dev/null +++ b/docs/configuration/vpn/index.rst @@ -0,0 +1,15 @@ +### +VPN +### + + +.. toctree:: + :maxdepth: 1 + :includehidden: + + ipsec + l2tp + openconnect + pptp + rsa-keys + sstp \ No newline at end of file diff --git a/docs/vpn/ipsec.rst b/docs/configuration/vpn/ipsec.rst similarity index 100% rename from docs/vpn/ipsec.rst rename to docs/configuration/vpn/ipsec.rst diff --git a/docs/vpn/l2tp.rst b/docs/configuration/vpn/l2tp.rst similarity index 100% rename from docs/vpn/l2tp.rst rename to docs/configuration/vpn/l2tp.rst diff --git a/docs/vpn/openconnect.rst b/docs/configuration/vpn/openconnect.rst similarity index 100% rename from docs/vpn/openconnect.rst rename to docs/configuration/vpn/openconnect.rst diff --git a/docs/vpn/pptp.rst b/docs/configuration/vpn/pptp.rst similarity index 100% rename from docs/vpn/pptp.rst rename to docs/configuration/vpn/pptp.rst diff --git a/docs/vpn/site2site_ipsec.rst b/docs/configuration/vpn/site2site_ipsec.rst similarity index 99% rename from docs/vpn/site2site_ipsec.rst rename to docs/configuration/vpn/site2site_ipsec.rst index 08ccc648..97f27b43 100644 --- a/docs/vpn/site2site_ipsec.rst +++ b/docs/configuration/vpn/site2site_ipsec.rst @@ -218,7 +218,7 @@ IKEv2 Imagine the following topology -.. figure:: ../_static/images/vpn_s2s_ikev2.png +.. figure:: /_static/images/vpn_s2s_ikev2.png :scale: 50 % :alt: IPSec IKEv2 site2site VPN diff --git a/docs/vpn/sstp.rst b/docs/configuration/vpn/sstp.rst similarity index 99% rename from docs/vpn/sstp.rst rename to docs/configuration/vpn/sstp.rst index f5e4ad05..dbaa41c0 100644 --- a/docs/vpn/sstp.rst +++ b/docs/configuration/vpn/sstp.rst @@ -344,4 +344,4 @@ A connection attempt will be shown as: .. _sstpc: https://github.com/reliablehosting/sstp-client -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/vrf.rst b/docs/configuration/vrf/index.rst similarity index 99% rename from docs/vrf.rst rename to docs/configuration/vrf/index.rst index 75075be6..a47175f2 100644 --- a/docs/vrf.rst +++ b/docs/configuration/vrf/index.rst @@ -304,4 +304,4 @@ For VR Fmaintenance the followin operational commands are in place. useful when the host specified is a hostname rather than an IP address. -.. include:: common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/configuration/zonepolicy/index.rst b/docs/configuration/zonepolicy/index.rst new file mode 100644 index 00000000..31784dc3 --- /dev/null +++ b/docs/configuration/zonepolicy/index.rst @@ -0,0 +1,8 @@ +########### +Zone Policy +########### + + +.. toctree:: + :maxdepth: 1 + :includehidden: \ No newline at end of file diff --git a/docs/contributing/debugging.rst b/docs/contributing/debugging.rst index fcd62c89..644545bf 100644 --- a/docs/contributing/debugging.rst +++ b/docs/contributing/debugging.rst @@ -143,4 +143,4 @@ order of the scripts. .. _vyatta-cfg: https://github.com/vyos/vyatta-cfg .. _bootchart.conf: https://github.com/vyos/vyos-build/blob/current/data/live-build-config/includes.chroot/etc/systemd/bootchart.conf -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/contributing/development.rst b/docs/contributing/development.rst index 0a7fecb5..73b8b22e 100644 --- a/docs/contributing/development.rst +++ b/docs/contributing/development.rst @@ -711,4 +711,4 @@ http://dev.packages.vyos.net/repositories/. .. _`VLAN (VIF)`: https://github.com/vyos/vyos-1x/tree/current/interface-definitions/include/vif.xml.i .. _`MAC address`: https://github.com/vyos/vyos-1x/tree/current/interface-definitions/include/interface-mac.xml.i -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/contributing/documentation.rst b/docs/contributing/documentation.rst index 0276a7d2..197f5b03 100644 --- a/docs/contributing/documentation.rst +++ b/docs/contributing/documentation.rst @@ -325,4 +325,4 @@ predefined structure. .. _reStructuredTextDirectives: https://docutils.sourceforge.io/docs/ref/rst/directives.html .. _README.md: https://github.com/vyos/vyos-documentation/blob/master/README.md -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/contributing/issues-features.rst b/docs/contributing/issues-features.rst index 473d49d9..9b6602f9 100644 --- a/docs/contributing/issues-features.rst +++ b/docs/contributing/issues-features.rst @@ -77,4 +77,4 @@ the left side under the specific project. .. _Slack: https://slack.vyos.io .. _Forum: https://forum.vyos.io -.. include:: /common-references.rst +.. include:: /_include/common-references.txt diff --git a/docs/coverage.rst b/docs/coverage.rst index f003f9ff..01d51e90 100644 --- a/docs/coverage.rst +++ b/docs/coverage.rst @@ -1,5 +1,3 @@ -:orphan: - ######## Coverage ######## diff --git a/docs/index.rst b/docs/index.rst index 96272fff..ed16b420 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,7 +22,7 @@ VyOS User Guide :caption: first steps installation/index - quickstart/index + quick-start cli .. toctree:: @@ -47,4 +47,5 @@ VyOS User Guide contributing/index + coverage copyright diff --git a/docs/installation/upate.rst b/docs/installation/update.rst similarity index 100% rename from docs/installation/upate.rst rename to docs/installation/update.rst diff --git a/docs/operation/index.rst b/docs/operation/index.rst index b40f769d..647b5b25 100644 --- a/docs/operation/index.rst +++ b/docs/operation/index.rst @@ -7,4 +7,5 @@ Operation Mode :includehidden: information - ip-command \ No newline at end of file + ip-commands + boot-options \ No newline at end of file diff --git a/docs/vpn/index.rst b/docs/vpn/index.rst deleted file mode 100644 index c208b3c0..00000000 --- a/docs/vpn/index.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _vpn: - -### -VPN -### - -.. toctree:: - :maxdepth: 2 - - dmvpn - ipsec - l2tp - openconnect - openvpn - pptp - site2site_ipsec - sstp - wireguard From 6f6950d14e46ef92d961682b23fb28936c23f9b7 Mon Sep 17 00:00:00 2001 From: rebortg Date: Mon, 7 Dec 2020 20:29:11 +0100 Subject: [PATCH 24/28] fix build errors after arrange --- docs/changelog/index.rst | 3 ++ docs/cli.rst | 9 ++--- docs/configuration/firewall/index.rst | 54 +++++++++++++++---------- docs/configuration/protocols/static.rst | 11 +++-- docs/configuration/system/index.rst | 10 ++++- docs/configuration/vpn/index.rst | 13 +++++- docs/configuration/vpn/rsa-keys.rst | 4 ++ docs/contributing/documentation.rst | 2 +- 8 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 docs/configuration/vpn/rsa-keys.rst diff --git a/docs/changelog/index.rst b/docs/changelog/index.rst index 26262932..8d2e8a86 100644 --- a/docs/changelog/index.rst +++ b/docs/changelog/index.rst @@ -1,3 +1,6 @@ +.. _release-notes: + + ######### Changelog ######### diff --git a/docs/cli.rst b/docs/cli.rst index 34ab3df6..7964c490 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -12,8 +12,7 @@ Operational Mode Operational mode allows for commands to perform operational system tasks and view system and service status, while configuration mode allows for the -modification of system configuration. The list of all operational level commands -is available at :ref:`operational_level_commands`. +modification of system configuration. The CLI provides a built-in help system. In the CLI the ``?`` key may be used to display available commands. The ``TAB`` key can be used to auto-complete @@ -75,9 +74,6 @@ When viewing in page mode the following commands are available: Configuration Mode ################## -The list of all operational level commands is available at -:ref:`configuration_level_commands`. - To enter configuration mode use the ``configure`` command: .. code-block:: none @@ -112,7 +108,8 @@ thus also be easily cloned by simply copying the required configuration files. Terminology -=========== +########### + live A VyOS system has three major types of configurations: diff --git a/docs/configuration/firewall/index.rst b/docs/configuration/firewall/index.rst index 2615774f..e95ecb53 100644 --- a/docs/configuration/firewall/index.rst +++ b/docs/configuration/firewall/index.rst @@ -1,11 +1,12 @@ .. _firewall: +######## Firewall -======== - +######## +******** Overview --------- +******** VyOS makes use of Linux `netfilter `_ for packet filtering. @@ -24,8 +25,9 @@ or zone based firewall policy. OS, is a reference to as `local` with respect to its input interface. +*************** Global settings ---------------- +*************** Some firewall settings are global and have a affect on the whole system. @@ -140,8 +142,9 @@ Some firewall settings are global and have a affect on the whole system. Set the global setting for related connections. +****** Groups ------- +****** Firewall groups represent collections of IP addresses, networks, or ports. Once created, a group can be referenced by firewall rules as @@ -158,7 +161,7 @@ names. Address Groups -************** +============== In a **address group** a single IP adresses or IP address ranges are definded. @@ -182,7 +185,7 @@ definded. Network Groups -************** +============== While **network groups** accept IP networks in CIDR notation, specific IP addresses can be added as a 32-bit prefix. If you foresee the need @@ -207,7 +210,7 @@ recommended. Port Groups -*********** +=========== A **port group** represents only port numbers, not the protocol. Port groups can be referenced for either TCP or UDP. It is recommended that @@ -232,8 +235,9 @@ filtering unnecessary ports. Ranges of ports can be specified by using Provide a port group description. +********* Rule-Sets ----------- +********* A rule-set is a named collection of firewall rules that can be applied to an interface or zone. Each rule is numbered, has an action to apply @@ -281,7 +285,7 @@ the action of the rule will executed. If you want to disable a rule but let it in the configuration. Matching criteria -***************** +================= There are a lot of matching criteria gainst which the package can be tested. @@ -413,8 +417,9 @@ There are a lot of matching criteria gainst which the package can be tested. Match against the state of a packet. +*********************************** Applying a Rule-Set to an Interface ------------------------------------ +*********************************** A Rule-Set can be appliend to every inteface: @@ -439,8 +444,9 @@ A Rule-Set can be appliend to every inteface: several interfaces. An interface can only have one rule-set per chain. +************************** Zone-based Firewall Policy --------------------------- +************************** As an alternative to applying policy to an interface directly, a zone-based firewall can be created to simplify configuration when @@ -453,7 +459,7 @@ An basic introduction to zone-based firewalls can be found `here and an example at :ref:`examples-zone-policy`. Define a Zone -************* +============= To define a zone setup either one with interfaces or a local zone. @@ -477,7 +483,7 @@ To define a zone setup either one with interfaces or a local zone. Applying a Rule-Set to a Zone -***************************** +============================= Before you are able to apply a rule-set to a zone you have to create the zones first. @@ -496,11 +502,12 @@ first. set zone-policy zone LAN from DMZ firewall name DMZv4-to-LANv4 +*********************** Operation-mode Firewall ------------------------ +*********************** Rule-set overview -***************** +================= .. opcmd:: show firewall @@ -663,7 +670,7 @@ Rule-set overview Zone-Policy Overview -******************** +==================== .. opcmd:: show zone-policy zone @@ -684,7 +691,7 @@ Zone-Policy Overview Show Firewall log -***************** +================= .. opcmd:: show log firewall [name | ipv6name] @@ -698,7 +705,7 @@ Show Firewall log Example Partial Config ----------------------- +====================== .. code-block:: none @@ -770,9 +777,10 @@ Example Partial Config .. _routing-mss-clamp: -################ + +**************** TCP-MSS Clamping -################ +**************** As Internet wide PMTU discovery rarely works, we sometimes need to clamp our TCP MSS value to a specific value. This is a field in the TCP @@ -788,9 +796,11 @@ value for IPv4 and IPv6. in 1452 bytes on a 1492 byte MTU. + IPv4 ==== + .. cfgcmd:: set firewall options interface adjust-mss Use this command to set the maximum segment size for IPv4 transit @@ -808,6 +818,8 @@ for your WireGuard `wg02` tunnel. set firewall options interface pppoe0 adjust-mss '1452' set firewall options interface wg02 adjust-mss '1372' + + IPv6 ==== diff --git a/docs/configuration/protocols/static.rst b/docs/configuration/protocols/static.rst index fbde8228..43b77c41 100644 --- a/docs/configuration/protocols/static.rst +++ b/docs/configuration/protocols/static.rst @@ -15,8 +15,9 @@ collection of all routes the router has learned from its configuration or from its dynamic routing protocols is stored in the RIB. Unicast routes are directly used to determine the forwarding table used for unicast packet forwarding. +************* Static Routes -############# +************* .. cfgcmd:: set protocols static route next-hop
@@ -152,8 +153,9 @@ provided by the Neighbor Discovery Protocol (NDP). To manipulate or display ARP_ table entries, the following commands are implemented. +********* Configure -========= +********* .. cfgcmd:: set protocols static arp
hwaddr @@ -166,8 +168,11 @@ Configure set protocols static arp 192.0.2.100 hwaddr 00:53:27:de:23:aa + +********* Operation -========= +********* + .. opcmd:: show protocols static arp diff --git a/docs/configuration/system/index.rst b/docs/configuration/system/index.rst index ecf09a64..4bb16c42 100644 --- a/docs/configuration/system/index.rst +++ b/docs/configuration/system/index.rst @@ -22,7 +22,7 @@ System name-server name-servers-dhcp ntp - options + option proxy static-host-mapping sysctl @@ -30,3 +30,11 @@ System task-scheduler time-zone wifi-requlatory-domain + + +.. toctree:: + :maxdepth: 1 + :includehidden: + + default-route + eventhandler diff --git a/docs/configuration/vpn/index.rst b/docs/configuration/vpn/index.rst index 397093c2..abaca198 100644 --- a/docs/configuration/vpn/index.rst +++ b/docs/configuration/vpn/index.rst @@ -12,4 +12,15 @@ VPN openconnect pptp rsa-keys - sstp \ No newline at end of file + sstp + + + +pages to sort + +.. toctree:: + :maxdepth: 1 + :includehidden: + + dmvpn + site2site_ipsec \ No newline at end of file diff --git a/docs/configuration/vpn/rsa-keys.rst b/docs/configuration/vpn/rsa-keys.rst new file mode 100644 index 00000000..9f289d0d --- /dev/null +++ b/docs/configuration/vpn/rsa-keys.rst @@ -0,0 +1,4 @@ + +######## +RSA-Keys +######## \ No newline at end of file diff --git a/docs/contributing/documentation.rst b/docs/contributing/documentation.rst index 197f5b03..f15595bf 100644 --- a/docs/contributing/documentation.rst +++ b/docs/contributing/documentation.rst @@ -261,7 +261,7 @@ Page content The documentation have 3 different types of pages, the same kind of pages must have the same structure to achieve a recognition factor. -For all *.rst files must follow the same TOC Level syntax and have to start with +For all rst files must follow the same TOC Level syntax and have to start with .. code-block:: From f0d6a0cbb8c4627f7b9f697508615c90c30f6e05 Mon Sep 17 00:00:00 2001 From: rebortg Date: Mon, 7 Dec 2020 20:47:32 +0100 Subject: [PATCH 25/28] contributing: improve documentation --- docs/contributing/documentation.rst | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/docs/contributing/documentation.rst b/docs/contributing/documentation.rst index f15595bf..1766d6ca 100644 --- a/docs/contributing/documentation.rst +++ b/docs/contributing/documentation.rst @@ -261,7 +261,7 @@ Page content The documentation have 3 different types of pages, the same kind of pages must have the same structure to achieve a recognition factor. -For all rst files must follow the same TOC Level syntax and have to start with +All RST files must follow the same TOC Level syntax and have to start with .. code-block:: @@ -272,8 +272,9 @@ For all rst files must follow the same TOC Level syntax and have to start with Configuration mode pages ^^^^^^^^^^^^^^^^^^^^^^^^ -A configuration mode article covers a specific level of a command. -The exact level depends on the command. +A configuration mode folder and article covers a specific level of a command. +The exact level depends on the command. This should provide stability for URLs +used in the forum or blogpost. For example: @@ -281,7 +282,7 @@ For example: * ``set interfaces ethernet`` is written in ``interfaces/ethernet.rst`` The article starts with a short intruducing about the command or the technologie. -Include some helpfull links or background informations. +Please include some helpfull links or background informations. After this a optional section follows. Some commands have requirements like the compatible hardware (e.g. Wifi) or some commands you have to set before. For @@ -290,28 +291,20 @@ example it is recommended to set a route-map before configure bgp. In the configuration part of the page all possible confiuration options should be documented. Use ``.. cfgcmd::`` like described above. -Related Operation command must be documented in the next part of the articel. +Related Operation command must be documented in the next part of the article. Use ``::opcmd..`` for these commands. If there some troubleshooting guides releated to the commands. Explain it in the next optional part. -Examples: - - * ssh - - - Operation mode pages ^^^^^^^^^^^^^^^^^^^^ Operation mode commands, which didn't fit in a related configuraton mode command must documented in this part of the documentation. -.. todo:: - - create structure - +General concepts for troubleshooting belong here as well as detailed process +descriptions. Anything else ^^^^^^^^^^^^^ From b0b5b6ff303d2c6bc01590a9aa80660211e8c99f Mon Sep 17 00:00:00 2001 From: rebortg Date: Mon, 7 Dec 2020 20:47:46 +0100 Subject: [PATCH 26/28] delete release page --- docs/index.rst | 1 - docs/introducing/releases.rst | 29 ----------------------------- 2 files changed, 30 deletions(-) delete mode 100644 docs/introducing/releases.rst diff --git a/docs/index.rst b/docs/index.rst index ed16b420..5d8bfd55 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,7 +11,6 @@ VyOS User Guide introducing/about introducing/history - introducing/releases changelog/index diff --git a/docs/introducing/releases.rst b/docs/introducing/releases.rst deleted file mode 100644 index 6d95c4bc..00000000 --- a/docs/introducing/releases.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. _release: - -######## -Releases -######## - -Rolling Release -############### - -rolling rolling - -LTS -### - -lts lts lts - - -old LTS -======= - -old LTSLTSLTSLTS - -even older LTS --------------- - -even older LTS even older LTS -even older LTS even older LTS even older LTS even older LTS even older LTS - - From cf83303fd11ec4f4973d7560d5802a2f942b9fe5 Mon Sep 17 00:00:00 2001 From: rebortg Date: Mon, 7 Dec 2020 21:17:07 +0100 Subject: [PATCH 27/28] fix submodule error in .readthedocs.yml --- .readthedocs.yml | 3 +-- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 7a4e84da..56ce79a7 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -24,5 +24,4 @@ python: - requirements: requirements.txt submodules: - include: - - vyos-1x \ No newline at end of file + include: all \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2b1f7796..03b34c63 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,4 @@ sphinx-rtd-theme setuptools docutils lxml -sphinx-notfound-page \ No newline at end of file +sphinx-notfound-page From 0bb741b58bc0dd7f0beae7364ed519f7165bdbb7 Mon Sep 17 00:00:00 2001 From: rebortg Date: Tue, 8 Dec 2020 14:38:56 +0100 Subject: [PATCH 28/28] Dockerfile: add python requirement lxml --- docker/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/Dockerfile b/docker/Dockerfile index 02b0fc26..903a8e83 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -33,6 +33,7 @@ RUN pip3 install Sphinx RUN pip3 install sphinx-rtd-theme RUN pip3 install sphinx-autobuild RUN pip3 install sphinx-notfound-page +RUN pip3 install lxml # Cleanup