commit d2d254e780a02489f4a80df3a951b3434b316132 Author: GitHub Actions Date: Fri Oct 3 00:27:59 2025 +0000 Deploy house-of-vanity/house-of-vanity.github.io to house-of-vanity/house-of-vanity.github.io:gh-pages diff --git a/404.html b/404.html new file mode 100644 index 0000000..f8414f0 --- /dev/null +++ b/404.html @@ -0,0 +1,3 @@ + +404 Not Found +

404 Not Found

diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..6b76e55 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +btwiusearch.net diff --git a/about/index.html b/about/index.html new file mode 100644 index 0000000..90f3fb9 --- /dev/null +++ b/about/index.html @@ -0,0 +1,257 @@ + + + + + + + + + + + About + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

About

+
+ + on 2023-08-25 + + +
+
+ + + +
+

Curriculum Vitae

+

Alexandr Bogomyakov

+

In love with GNU/Linux, Python and Rust.

+

Site Reliability Engineer (SRE) at Criteo

+

Limassol, Cyprus 🇨🇾

+
+

Me

+

Contacts

+ +
+

Education

+ + + +
YearsDegree
2009-2014Bachelor in EconomicsPacific National University, Khabarovsk, Russia
2005-2019Bachelor in Computer ScienceBauman Moscow State Technical University, Moscow, Russia
+
+

Experience

+

Criteo - Senior Site Reliability Engineer

+

May 2022 - Present Cyprus, Limassol (former Iponweb)

+
+

Pioneers in applying machine learning to solving digital advertising’s biggest challenges, offer world-leading technology solutions for building and operating scalable, algorithmically complex media trading systems for innovative companies across the advertising spectrum.

+
+
    +
  • Cassandra
  • +
  • Kubernetes
  • +
  • Google cloud platform
  • +
  • AWS
  • +
  • Terraform
  • +
  • Puppet
  • +
  • Python
  • +
  • Linux
  • +
+

VK Group - Senior Site Reliability Engineer

+

May 2021 - May 2022 Russia, Moscow

+
+

Mail.ru Group, LLC is a Russian internet company. It was started in 1998 as an e-mail service and went on to become a major corporate figure in the Russian-speaking segment of the Internet. As of 2013 according to comScore, websites owned by Mail.ru collectively had the largest audience in Russia and captured the most screen time. Mail.ru's sites reach approximately 86% of Russian Internet users on a monthly basis and the company is in the top 5 of largest Internet companies, based on the number of total pages viewed.

+
+
    +
  • Maintain Kubernetes on bare metal
  • +
  • Puppet
  • +
  • Python
  • +
  • Linux
  • +
+

EPAM - DevOps

+

Sep 2020 - May 2021 Russia, Moscow

+
+

EPAM Systems, Inc. is an American company that specializes in product development, digital platform engineering, and digital and product design. The world's largest manufacturer of custom software, consulting specialist, resident of the Belarusian High Technologies Park. Its branches are represented in more than 30 countries of the world.

+
+
    +
  • Maintain infrastructure in clouds using Ansible, Terraform.
  • +
  • Develop and maintain automation tools.
  • +
  • Build CI/CD pipelines with Jenkins Pipelines.
  • +
  • Service containerization expirience with AWS ECS Fargate.
  • +
+

IPONWEB - Operations Engineer

+

Nov 2016 - Sep 2020 Russia, Moscow

+
+

IPONWEB is a pioneer and global leader in the engineering of advanced programmatic, RTB, and media trading platforms across digital, TV, DOOH, and audio. Founded in the UK, IPONWEB has nearly 400 employees spread across the US, UK, Germany, Japan, Asia and Russia.

+
+
    +
  • Cassandra
  • +
  • Kubernetes
  • +
  • Google cloud platform
  • +
  • AWS
  • +
  • Terraform
  • +
  • Puppet
  • +
  • Python
  • +
  • Linux
  • +
+
+ +
+ + + +
+
+ + + + + + + + + +
+ + + diff --git a/css/dark.css b/css/dark.css new file mode 100644 index 0000000..54615aa --- /dev/null +++ b/css/dark.css @@ -0,0 +1,181 @@ +body { + color: white; + background-color: #202124; +} + +::-moz-selection { + background: blue; + color: #fff; + text-shadow: none; +} + +::selection { + background: red; + color: #fff; + text-shadow: none; +} + +hr { + border-top: 3px dotted blue; +} + +code { + background-color: lightblue; + color: black; + text-decoration: bold; + padding: 0.1em 0.2em; +} + +pre { + background-color: #272822; + line-height: 1.4; + overflow-x: auto; + padding: 1em; +} + +blockquote { + border-color: blue; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + color: #ddd; +} + +h1::before { + color: var(--darkMaincolor); + content: "# "; +} + +h2::before { + color: var(--darkMaincolor); + content: "## "; +} + +h3::before { + color: var(--darkMaincolor); + content: "### "; +} + +h4::before { + color: var(--darkMaincolor); + content: "#### "; +} + +h5::before { + color: var(--darkMaincolor); + content: "##### "; +} + +h6::before { + color: var(--darkMaincolor); + content: "###### "; +} + +a { + border-bottom: 3px solid var(--darkMaincolor); + color: inherit; +} + +a:hover { + background-color: var(--darkMaincolor); + color: black; +} + +.site-description a { + color: #ddd; +} + +.site-description a:hover { + color: black; +} + +.tags a { + border-bottom: 3px solid var(--darkMaincolor); +} + +.tags a:hover { + background-color: var(--darkMaincolor); + color: black; +} + +.site-title a { + color: white; + text-decoration: none !important; +} + +.header nav, +.footer { + border-color: #333; +} + +.highlight { + background-color: #333; +} + +.soc:hover { + color: black; +} + +.draft-label { + color: var(--darkMaincolor); + background-color: blue; +} + +.highlight pre code[class=language-javaScript]::before, +.highlight pre code[class="language-js"]::before { + content: "js"; + background: #f7df1e; + color: black; +} + +.highlight pre code[class*='language-yml']::before, +.highlight pre code[class*='language-yaml']::before { + content: 'yaml'; + background: #f71e6a; + color: white; +} + +.highlight pre code[class*='language-shell']::before, +.highlight pre code[class*='language-bash']::before, +.highlight pre code[class*='language-sh']::before { + content: 'shell'; + background: green; + color: white +} + +.highlight pre code[class*='language-json']::before { + content: 'json'; + background: dodgerblue; + color: #000000 +} + +.highlight pre code[class*='language-python']::before, +.highlight pre code[class*='language-py']::before { + content: 'py'; + background: blue; + color: yellow; +} + +.highlight pre code[class*='language-css']::before { + content: 'css'; + background: cyan; + color: black; +} + +.highlight pre code[class*='language-go']::before { + content: 'Go'; + background: cyan; + color: royalblue; +} + +.highlight pre code[class*='language-md']::before, +.highlight pre code[class*='language-md']::before { + content: 'Markdown'; + background: royalblue; + color: whitesmoke; +} \ No newline at end of file diff --git a/css/fonts.css b/css/fonts.css new file mode 100644 index 0000000..156ee63 --- /dev/null +++ b/css/fonts.css @@ -0,0 +1,38 @@ +/* fira-sans-regular - latin */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 400; + src: url('../fonts/fira-sans-v10-latin-regular.eot'); /* IE9 Compat Modes */ + src: local('Fira Sans Regular'), local('FiraSans-Regular'), + url('../fonts/fira-sans-v10-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/fira-sans-v10-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/fira-sans-v10-latin-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/fira-sans-v10-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/fira-sans-v10-latin-regular.svg#FiraSans') format('svg'); /* Legacy iOS */ +} +/* roboto-mono-regular - latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + src: url('../fonts/roboto-mono-v12-latin-regular.eot'); /* IE9 Compat Modes */ + src: url('../fonts/roboto-mono-v12-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/roboto-mono-v12-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/roboto-mono-v12-latin-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/roboto-mono-v12-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/roboto-mono-v12-latin-regular.svg#RobotoMono') format('svg'); /* Legacy iOS */ +} +/* ibm-plex-mono-500italic - latin */ +@font-face { + font-family: 'IBM Plex Mono'; + font-style: italic; + font-weight: 500; + src: url('../fonts/ibm-plex-mono-v6-latin-500italic.eot'); /* IE9 Compat Modes */ + src: local('IBM Plex Mono Medium Italic'), local('IBMPlexMono-MediumItalic'), + url('../fonts/ibm-plex-mono-v6-latin-500italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/ibm-plex-mono-v6-latin-500italic.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/ibm-plex-mono-v6-latin-500italic.woff') format('woff'), /* Modern Browsers */ + url('../fonts/ibm-plex-mono-v6-latin-500italic.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/ibm-plex-mono-v6-latin-500italic.svg#IBMPlexMono') format('svg'); /* Legacy iOS */ +} diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..06e1e15 --- /dev/null +++ b/css/main.css @@ -0,0 +1,421 @@ +/* Markdown */ +:root { + --maincolor: red; + --bordercl: rebeccapurple; + --callouctcolor: dodgerblue; + --hovercolor: navy; + --darkMaincolor: #50fa7b; +} + +html { + color: #232333; + font-family: "Roboto Mono", monospace; + font-size: 15px; + line-height: 1.6em; +} + +body { + display: block; + margin: 8px; +} + +* { + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +@keyframes intro { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.content { + animation: intro 0.3s both; + animation-delay: 0.15s; +} + +::selection { + background: var(--maincolor); + color: #fff; +} + +p { + /* font-family: 'Fira Sans', sans-serif; */ + line-height: 1.5; +} + +hr { + border: 0; + border-top: 3px dotted var(--bordercl); + margin: 1em 0; +} + +blockquote { + border-left: 3px solid var(--bordercl); + color: #737373; + margin: 0; + padding-left: 1em; +} + +a { + border-bottom: 3px solid var(--maincolor); + color: inherit; + text-decoration: none; +} + +a:hover { + background-color: var(--hovercolor); + color: #fff; +} + +ul { + list-style: none; + padding-left: 2ch; +} + +ul li { + text-indent: -2ch; +} + +ul>li::before { + content: "* "; + font-weight: bold; +} + +/* Images */ +img { + border: 3px solid #ececec; + max-width: 100%; +} + +figure { + box-sizing: border-box; + display: inline-block; + margin: 0; + max-width: 100%; +} + +figure img { + max-height: 500px; +} + +@media screen and (min-width: 600px) { + figure { + padding: 0 40px; + } +} + +figure h4 { + font-size: 1rem; + margin: 0; + margin-bottom: 1em; +} + +figure h4::before { + content: "↳ "; +} + +/* Code blocks */ +code { + background-color: #f1f1f1; + padding: 0.1em 0.2em; +} + +pre { + background-color: #ececec; + line-height: 1.4; + overflow-x: auto; + padding: 1em; +} + +.highlight pre ::selection { + background: rgba(255, 255, 255, 0.2); + color: inherit; +} + +pre code { + background-color: transparent; + color: inherit; + font-size: 100%; + padding: 0; +} + +/* Containers */ +.content { + margin-bottom: 4em; + margin-left: auto; + margin-right: auto; + max-width: 800px; + padding: 0 1ch; + word-wrap: break-word; +} + +/* Header */ +header { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + margin: 1em 0; +} + +header .main { + font-size: 1.5rem; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: 1.2rem; + margin-top: 2em; +} + +h1::before { + color: var(--maincolor); + content: "# "; +} + +h2::before { + color: var(--maincolor); + content: "## "; +} + +h3::before { + color: var(--maincolor); + content: "### "; +} + +h4::before { + color: var(--maincolor); + content: "#### "; +} + +h5::before { + color: var(--maincolor); + content: "##### "; +} + +h6::before { + color: var(--maincolor); + content: "###### "; +} + +.meta { + color: #999; + letter-spacing: -0.5px; +} + +/* Footer */ +footer { + display: flex; + align-items: center; + border-top: 0.4rem dotted var(--bordercl); + padding: 2rem 0rem; + margin-top: 2rem; +} + +.soc { + display: flex; + align-items: center; + padding-right: 1rem; + margin-right: 1rem; + border-right: 2px solid; + border-bottom: none; +} + +.footer-info { + padding: var(--footer-padding); +} + +#main_title { + margin-bottom: 10px; +} + +/* Common */ +.title h1 { + margin-bottom: 0; +} + +time { + color: grey; +} + +span { + color: grey; +} + + +/* Posts */ +article .title { + margin-bottom: 1em; +} + +/* Callout */ +.callout { + background-color: var(--callouctcolor); + color: #fff; + padding: 1em; +} + +.callout p { + /* font-family: 'IBM Plex Mono', monospace; */ + margin: 0; +} + +.callout a { + border-bottom: 3px solid #fff; +} + +.callout a:hover { + background-color: #fff; + color: var(--callouctcolor); +} + +.site-description { + display: flex; + justify-content: space-between; +} + +.tags li::before { + content: "🏷 "; +} + +.tags a { + border-bottom: 3px solid var(--maincolor); +} + +.tags a:hover { + color: white; + background-color: var(--hovercolor); +} + +svg { + max-height: 15px; +} + +.soc:hover { + color: white; +} + +.draft-label { + color: var(--bordercl); + text-decoration: none; + padding: 2px 4px; + border-radius: 4px; + margin-left: 6px; + background-color: #f9f2f4; +} + +pre { + font-family: "Roboto Mono", monospace; + position: relative; + -webkit-overflow-scrolling: touch; +} + +pre code[class*="language-"] { + -webkit-overflow-scrolling: touch; +} + +pre code[class*="language-"]::before { + background: black; + border-radius: 0 0 0.25rem 0.25rem; + color: white; + font-size: 12px; + letter-spacing: 0.025rem; + padding: 0.1rem 0.5rem; + position: absolute; + right: 1rem; + text-align: right; + text-transform: uppercase; + top: 0; +} + +pre code[class="language-javaScript"]::before, +pre code[class="language-js"]::before { + content: "js"; + background: #f7df1e; + color: black; +} + +pre code[class*="language-yml"]::before, +pre code[class*="language-yaml"]::before { + content: "yaml"; + background: #f71e6a; + color: white; +} + +pre code[class*="language-shell"]::before, +pre code[class*="language-bash"]::before, +pre code[class*="language-sh"]::before { + content: "shell"; + background: green; + color: white; +} + +pre code[class*="language-json"]::before { + content: "json"; + background: dodgerblue; + color: #000000; +} + +pre code[class*="language-python"]::before, +pre code[class*="language-py"]::before { + content: "py"; + background: blue; + color: yellow; +} + +pre code[class*="language-css"]::before { + content: "css"; + background: cyan; + color: black; +} + +pre code[class*="language-go"]::before { + content: "Go"; + background: cyan; + color: royalblue; +} + +pre code[class*="language-md"]::before, +pre code[class*="language-md"]::before { + content: "Markdown"; + background: royalblue; + color: whitesmoke; +} + +pre code[class*="language-rust"]::before, +pre code[class*="language-rs"]::before { + content: "rust"; + background: #fff8f6; + color: #ff4647; +} + +/* table */ +table { + border-spacing: 0; + border-collapse: collapse; +} + +table th { + padding: 6px 13px; + border: 1px solid #dfe2e5; + font-size: large; +} + +table td { + padding: 6px 13px; + border: 1px solid #dfe2e5; +} + +.footnote-definition { + display: flex; + align-items: center; + grid-column-gap: 10px; +} \ No newline at end of file diff --git a/fonts/fira-sans-v10-latin-regular.eot b/fonts/fira-sans-v10-latin-regular.eot new file mode 100644 index 0000000..7abf4c2 Binary files /dev/null and b/fonts/fira-sans-v10-latin-regular.eot differ diff --git a/fonts/fira-sans-v10-latin-regular.svg b/fonts/fira-sans-v10-latin-regular.svg new file mode 100644 index 0000000..1e52097 --- /dev/null +++ b/fonts/fira-sans-v10-latin-regular.svg @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fonts/fira-sans-v10-latin-regular.ttf b/fonts/fira-sans-v10-latin-regular.ttf new file mode 100644 index 0000000..572e442 Binary files /dev/null and b/fonts/fira-sans-v10-latin-regular.ttf differ diff --git a/fonts/fira-sans-v10-latin-regular.woff b/fonts/fira-sans-v10-latin-regular.woff new file mode 100644 index 0000000..d99ba57 Binary files /dev/null and b/fonts/fira-sans-v10-latin-regular.woff differ diff --git a/fonts/fira-sans-v10-latin-regular.woff2 b/fonts/fira-sans-v10-latin-regular.woff2 new file mode 100644 index 0000000..9bb5760 Binary files /dev/null and b/fonts/fira-sans-v10-latin-regular.woff2 differ diff --git a/fonts/ibm-plex-mono-v6-latin-500italic.eot b/fonts/ibm-plex-mono-v6-latin-500italic.eot new file mode 100644 index 0000000..62b89b3 Binary files /dev/null and b/fonts/ibm-plex-mono-v6-latin-500italic.eot differ diff --git a/fonts/ibm-plex-mono-v6-latin-500italic.svg b/fonts/ibm-plex-mono-v6-latin-500italic.svg new file mode 100644 index 0000000..6423805 --- /dev/null +++ b/fonts/ibm-plex-mono-v6-latin-500italic.svg @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fonts/ibm-plex-mono-v6-latin-500italic.ttf b/fonts/ibm-plex-mono-v6-latin-500italic.ttf new file mode 100644 index 0000000..e4d1ddf Binary files /dev/null and b/fonts/ibm-plex-mono-v6-latin-500italic.ttf differ diff --git a/fonts/ibm-plex-mono-v6-latin-500italic.woff b/fonts/ibm-plex-mono-v6-latin-500italic.woff new file mode 100644 index 0000000..4504b41 Binary files /dev/null and b/fonts/ibm-plex-mono-v6-latin-500italic.woff differ diff --git a/fonts/ibm-plex-mono-v6-latin-500italic.woff2 b/fonts/ibm-plex-mono-v6-latin-500italic.woff2 new file mode 100644 index 0000000..489745d Binary files /dev/null and b/fonts/ibm-plex-mono-v6-latin-500italic.woff2 differ diff --git a/fonts/roboto-mono-v12-latin-regular.eot b/fonts/roboto-mono-v12-latin-regular.eot new file mode 100644 index 0000000..8c56483 Binary files /dev/null and b/fonts/roboto-mono-v12-latin-regular.eot differ diff --git a/fonts/roboto-mono-v12-latin-regular.svg b/fonts/roboto-mono-v12-latin-regular.svg new file mode 100644 index 0000000..1864328 --- /dev/null +++ b/fonts/roboto-mono-v12-latin-regular.svg @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fonts/roboto-mono-v12-latin-regular.ttf b/fonts/roboto-mono-v12-latin-regular.ttf new file mode 100644 index 0000000..d5dee83 Binary files /dev/null and b/fonts/roboto-mono-v12-latin-regular.ttf differ diff --git a/fonts/roboto-mono-v12-latin-regular.woff b/fonts/roboto-mono-v12-latin-regular.woff new file mode 100644 index 0000000..f319fbf Binary files /dev/null and b/fonts/roboto-mono-v12-latin-regular.woff differ diff --git a/fonts/roboto-mono-v12-latin-regular.woff2 b/fonts/roboto-mono-v12-latin-regular.woff2 new file mode 100644 index 0000000..ed384d2 Binary files /dev/null and b/fonts/roboto-mono-v12-latin-regular.woff2 differ diff --git a/icon/favicon.png b/icon/favicon.png new file mode 100644 index 0000000..cce24c3 Binary files /dev/null and b/icon/favicon.png differ diff --git a/imgs/arch-01.png b/imgs/arch-01.png new file mode 100644 index 0000000..fd77eb1 Binary files /dev/null and b/imgs/arch-01.png differ diff --git a/imgs/arch-02.png b/imgs/arch-02.png new file mode 100644 index 0000000..bc40158 Binary files /dev/null and b/imgs/arch-02.png differ diff --git a/imgs/demo-01.png b/imgs/demo-01.png new file mode 100644 index 0000000..d624c44 Binary files /dev/null and b/imgs/demo-01.png differ diff --git a/imgs/photo.jpeg b/imgs/photo.jpeg new file mode 100644 index 0000000..e8a4114 Binary files /dev/null and b/imgs/photo.jpeg differ diff --git a/imgs/star-history.png b/imgs/star-history.png new file mode 100644 index 0000000..389a6c9 Binary files /dev/null and b/imgs/star-history.png differ diff --git a/imgs/vs-01.png b/imgs/vs-01.png new file mode 100644 index 0000000..55b32b2 Binary files /dev/null and b/imgs/vs-01.png differ diff --git a/imgs/vs-02.png b/imgs/vs-02.png new file mode 100644 index 0000000..bab32c0 Binary files /dev/null and b/imgs/vs-02.png differ diff --git a/imgs/vs-03.png b/imgs/vs-03.png new file mode 100644 index 0000000..857249d Binary files /dev/null and b/imgs/vs-03.png differ diff --git a/imgs/webview.png b/imgs/webview.png new file mode 100644 index 0000000..1b106d9 Binary files /dev/null and b/imgs/webview.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..e4f6115 --- /dev/null +++ b/index.html @@ -0,0 +1,409 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+
+ +

My own small public place

+ + +
+ + +
+ + + + + + + + + + + + + +
+ + + diff --git a/js/feather.min.js b/js/feather.min.js new file mode 100644 index 0000000..d229492 --- /dev/null +++ b/js/feather.min.js @@ -0,0 +1,13 @@ +!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.feather=n():e.feather=n()}("undefined"!=typeof self?self:this,function(){return function(e){var n={};function i(l){if(n[l])return n[l].exports;var t=n[l]={i:l,l:!1,exports:{}};return e[l].call(t.exports,t,t.exports,i),t.l=!0,t.exports}return i.m=e,i.c=n,i.d=function(e,n,l){i.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:l})},i.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},i.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(n,"a",n),n},i.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},i.p="",i(i.s=61)}([function(e,n,i){var l=i(20)("wks"),t=i(11),r=i(1).Symbol,o="function"==typeof r;(e.exports=function(e){return l[e]||(l[e]=o&&r[e]||(o?r:t)("Symbol."+e))}).store=l},function(e,n){var i=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=i)},function(e,n){var i=e.exports={version:"2.5.6"};"number"==typeof __e&&(__e=i)},function(e,n){var i={}.hasOwnProperty;e.exports=function(e,n){return i.call(e,n)}},function(e,n,i){e.exports=!i(27)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,n,i){var l=i(13);e.exports=function(e){if(!l(e))throw TypeError(e+" is not an object!");return e}},function(e,n,i){var l=i(5),t=i(56),r=i(55),o=Object.defineProperty;n.f=i(4)?Object.defineProperty:function(e,n,i){if(l(e),n=r(n,!0),l(i),t)try{return o(e,n,i)}catch(e){}if("get"in i||"set"in i)throw TypeError("Accessors not supported!");return"value"in i&&(e[n]=i.value),e}},function(e,n,i){var l=i(6),t=i(12);e.exports=i(4)?function(e,n,i){return l.f(e,n,t(1,i))}:function(e,n,i){return e[n]=i,e}},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var l=o(i(35)),t=o(i(33)),r=o(i(32));function o(e){return e&&e.__esModule?e:{default:e}}n.default=Object.keys(t.default).map(function(e){return new l.default(e,t.default[e],r.default[e])}).reduce(function(e,n){return e[n.name]=n,e},{})},function(e,n,i){var l=i(20)("keys"),t=i(11);e.exports=function(e){return l[e]||(l[e]=t(e))}},function(e,n){e.exports={}},function(e,n){var i=0,l=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++i+l).toString(36))}},function(e,n){e.exports=function(e,n){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:n}}},function(e,n){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,n){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,n){var i=Math.ceil,l=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?l:i)(e)}},function(e,n,i){var l; +/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ +/*! + Copyright (c) 2016 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ +!function(){"use strict";var i=function(){function e(){}function n(e,n){for(var i=n.length,l=0;l0?t(l(e),9007199254740991):0}},function(e,n){var i={}.toString;e.exports=function(e){return i.call(e).slice(8,-1)}},function(e,n,i){var l=i(48),t=i(14);e.exports=function(e){return l(t(e))}},function(e,n,i){var l=i(54);e.exports=function(e,n,i){if(l(e),void 0===n)return e;switch(i){case 1:return function(i){return e.call(n,i)};case 2:return function(i,l){return e.call(n,i,l)};case 3:return function(i,l,t){return e.call(n,i,l,t)}}return function(){return e.apply(n,arguments)}}},function(e,n,i){var l=i(1),t=i(7),r=i(3),o=i(11)("src"),a=Function.toString,c=(""+a).split("toString");i(2).inspectSource=function(e){return a.call(e)},(e.exports=function(e,n,i,a){var y="function"==typeof i;y&&(r(i,"name")||t(i,"name",n)),e[n]!==i&&(y&&(r(i,o)||t(i,o,e[n]?""+e[n]:c.join(String(n)))),e===l?e[n]=i:a?e[n]?e[n]=i:t(e,n,i):(delete e[n],t(e,n,i)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[o]||a.call(this)})},function(e,n,i){var l=i(13),t=i(1).document,r=l(t)&&l(t.createElement);e.exports=function(e){return r?t.createElement(e):{}}},function(e,n){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,n,i){var l=i(1),t=i(2),r=i(7),o=i(25),a=i(24),c=function(e,n,i){var y,p,h,x,s=e&c.F,u=e&c.G,d=e&c.S,f=e&c.P,v=e&c.B,g=u?l:d?l[n]||(l[n]={}):(l[n]||{}).prototype,m=u?t:t[n]||(t[n]={}),M=m.prototype||(m.prototype={});for(y in u&&(i=n),i)h=((p=!s&&g&&void 0!==g[y])?g:i)[y],x=v&&p?a(h,l):f&&"function"==typeof h?a(Function.call,h):h,g&&o(g,y,h,e&c.U),m[y]!=h&&r(m,y,x),f&&M[y]!=h&&(M[y]=h)};l.core=t,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,n){e.exports=!1},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var l=Object.assign||function(e){for(var n=1;n0&&void 0!==arguments[0]?arguments[0]:{};if("undefined"==typeof document)throw new Error("`feather.replace()` only works in a browser environment.");var n=document.querySelectorAll("[data-feather]");Array.from(n).forEach(function(n){return function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=function(e){return Array.from(e.attributes).reduce(function(e,n){return e[n.name]=n.value,e},{})}(e),o=i["data-feather"];delete i["data-feather"];var a=r.default[o].toSvg(l({},n,i,{class:(0,t.default)(n.class,i.class)})),c=(new DOMParser).parseFromString(a,"image/svg+xml").querySelector("svg");e.parentNode.replaceChild(c,e)}(n,e)})}},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var l,t=i(8),r=(l=t)&&l.__esModule?l:{default:l};n.default=function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(console.warn("feather.toSvg() is deprecated. Please use feather.icons[name].toSvg() instead."),!e)throw new Error("The required `key` (icon name) parameter is missing.");if(!r.default[e])throw new Error("No icon matching '"+e+"'. See the complete list of icons at https://feathericons.com");return r.default[e].toSvg(n)}},function(e){e.exports={activity:["pulse","health","action","motion"],airplay:["stream","cast","mirroring"],"alert-circle":["warning"],"alert-octagon":["warning"],"alert-triangle":["warning"],"at-sign":["mention"],award:["achievement","badge"],aperture:["camera","photo"],bell:["alarm","notification"],"bell-off":["alarm","notification","silent"],bluetooth:["wireless"],"book-open":["read"],book:["read","dictionary","booklet","magazine"],bookmark:["read","clip","marker","tag"],briefcase:["work","bag","baggage","folder"],clipboard:["copy"],clock:["time","watch","alarm"],"cloud-drizzle":["weather","shower"],"cloud-lightning":["weather","bolt"],"cloud-rain":["weather"],"cloud-snow":["weather","blizzard"],cloud:["weather"],codepen:["logo"],codesandbox:["logo"],coffee:["drink","cup","mug","tea","cafe","hot","beverage"],command:["keyboard","cmd"],compass:["navigation","safari","travel"],copy:["clone","duplicate"],"corner-down-left":["arrow"],"corner-down-right":["arrow"],"corner-left-down":["arrow"],"corner-left-up":["arrow"],"corner-right-down":["arrow"],"corner-right-up":["arrow"],"corner-up-left":["arrow"],"corner-up-right":["arrow"],"credit-card":["purchase","payment","cc"],crop:["photo","image"],crosshair:["aim","target"],database:["storage"],delete:["remove"],disc:["album","cd","dvd","music"],"dollar-sign":["currency","money","payment"],droplet:["water"],edit:["pencil","change"],"edit-2":["pencil","change"],"edit-3":["pencil","change"],eye:["view","watch"],"eye-off":["view","watch"],"external-link":["outbound"],facebook:["logo"],"fast-forward":["music"],figma:["logo","design","tool"],film:["movie","video"],"folder-minus":["directory"],"folder-plus":["directory"],folder:["directory"],frown:["emoji","face","bad","sad","emotion"],gift:["present","box","birthday","party"],"git-branch":["code","version control"],"git-commit":["code","version control"],"git-merge":["code","version control"],"git-pull-request":["code","version control"],github:["logo","version control"],gitlab:["logo","version control"],global:["world","browser","language","translate"],"hard-drive":["computer","server"],hash:["hashtag","number","pound"],headphones:["music","audio"],heart:["like","love"],"help-circle":["question mark"],hexagon:["shape","node.js","logo"],home:["house"],image:["picture"],inbox:["email"],instagram:["logo","camera"],key:["password","login","authentication"],"life-bouy":["help","life ring","support"],linkedin:["logo"],lock:["security","password"],"log-in":["sign in","arrow"],"log-out":["sign out","arrow"],mail:["email"],"map-pin":["location","navigation","travel","marker"],map:["location","navigation","travel"],maximize:["fullscreen"],"maximize-2":["fullscreen","arrows"],meh:["emoji","face","neutral","emotion"],menu:["bars","navigation","hamburger"],"message-circle":["comment","chat"],"message-square":["comment","chat"],"mic-off":["record"],mic:["record"],minimize:["exit fullscreen"],"minimize-2":["exit fullscreen","arrows"],monitor:["tv"],moon:["dark","night"],"more-horizontal":["ellipsis"],"more-vertical":["ellipsis"],"mouse-pointer":["arrow","cursor"],move:["arrows"],navigation:["location","travel"],"navigation-2":["location","travel"],octagon:["stop"],package:["box"],paperclip:["attachment"],pause:["music","stop"],"pause-circle":["music","stop"],"pen-tool":["vector","drawing"],play:["music","start"],"play-circle":["music","start"],plus:["add","new"],"plus-circle":["add","new"],"plus-square":["add","new"],pocket:["logo","save"],power:["on","off"],radio:["signal"],rewind:["music"],rss:["feed","subscribe"],save:["floppy disk"],search:["find","magnifier","magnifying glass"],send:["message","mail","paper airplane"],settings:["cog","edit","gear","preferences"],shield:["security"],"shield-off":["security"],"shopping-bag":["ecommerce","cart","purchase","store"],"shopping-cart":["ecommerce","cart","purchase","store"],shuffle:["music"],"skip-back":["music"],"skip-forward":["music"],slash:["ban","no"],sliders:["settings","controls"],smile:["emoji","face","happy","good","emotion"],speaker:["music"],star:["bookmark","favorite","like"],sun:["brightness","weather","light"],sunrise:["weather"],sunset:["weather"],tag:["label"],target:["bullseye"],terminal:["code","command line"],"thumbs-down":["dislike","bad"],"thumbs-up":["like","good"],"toggle-left":["on","off","switch"],"toggle-right":["on","off","switch"],trash:["garbage","delete","remove"],"trash-2":["garbage","delete","remove"],triangle:["delta"],truck:["delivery","van","shipping"],twitter:["logo"],umbrella:["rain","weather"],"video-off":["camera","movie","film"],video:["camera","movie","film"],voicemail:["phone"],volume:["music","sound","mute"],"volume-1":["music","sound"],"volume-2":["music","sound"],"volume-x":["music","sound","mute"],watch:["clock","time"],wind:["weather","air"],"x-circle":["cancel","close","delete","remove","times"],"x-octagon":["delete","stop","alert","warning","times"],"x-square":["cancel","close","delete","remove","times"],x:["cancel","close","delete","remove","times"],youtube:["logo","video","play"],"zap-off":["flash","camera","lightning"],zap:["flash","camera","lightning"]}},function(e){e.exports={activity:'',airplay:'',"alert-circle":'',"alert-octagon":'',"alert-triangle":'',"align-center":'',"align-justify":'',"align-left":'',"align-right":'',anchor:'',aperture:'',archive:'',"arrow-down-circle":'',"arrow-down-left":'',"arrow-down-right":'',"arrow-down":'',"arrow-left-circle":'',"arrow-left":'',"arrow-right-circle":'',"arrow-right":'',"arrow-up-circle":'',"arrow-up-left":'',"arrow-up-right":'',"arrow-up":'',"at-sign":'',award:'',"bar-chart-2":'',"bar-chart":'',"battery-charging":'',battery:'',"bell-off":'',bell:'',bluetooth:'',bold:'',"book-open":'',book:'',bookmark:'',box:'',briefcase:'',calendar:'',"camera-off":'',camera:'',cast:'',"check-circle":'',"check-square":'',check:'',"chevron-down":'',"chevron-left":'',"chevron-right":'',"chevron-up":'',"chevrons-down":'',"chevrons-left":'',"chevrons-right":'',"chevrons-up":'',chrome:'',circle:'',clipboard:'',clock:'',"cloud-drizzle":'',"cloud-lightning":'',"cloud-off":'',"cloud-rain":'',"cloud-snow":'',cloud:'',code:'',codepen:'',codesandbox:'',coffee:'',columns:'',command:'',compass:'',copy:'',"corner-down-left":'',"corner-down-right":'',"corner-left-down":'',"corner-left-up":'',"corner-right-down":'',"corner-right-up":'',"corner-up-left":'',"corner-up-right":'',cpu:'',"credit-card":'',crop:'',crosshair:'',database:'',delete:'',disc:'',"dollar-sign":'',"download-cloud":'',download:'',droplet:'',"edit-2":'',"edit-3":'',edit:'',"external-link":'',"eye-off":'',eye:'',facebook:'',"fast-forward":'',feather:'',figma:'',"file-minus":'',"file-plus":'',"file-text":'',file:'',film:'',filter:'',flag:'',"folder-minus":'',"folder-plus":'',folder:'',frown:'',gift:'',"git-branch":'',"git-commit":'',"git-merge":'',"git-pull-request":'',github:'',gitlab:'',globe:'',grid:'',"hard-drive":'',hash:'',headphones:'',heart:'',"help-circle":'',hexagon:'',home:'',image:'',inbox:'',info:'',instagram:'',italic:'',key:'',layers:'',layout:'',"life-buoy":'',"link-2":'',link:'',linkedin:'',list:'',loader:'',lock:'',"log-in":'',"log-out":'',mail:'',"map-pin":'',map:'',"maximize-2":'',maximize:'',meh:'',menu:'',"message-circle":'',"message-square":'',"mic-off":'',mic:'',"minimize-2":'',minimize:'',"minus-circle":'',"minus-square":'',minus:'',monitor:'',moon:'',"more-horizontal":'',"more-vertical":'',"mouse-pointer":'',move:'',music:'',"navigation-2":'',navigation:'',octagon:'',package:'',paperclip:'',"pause-circle":'',pause:'',"pen-tool":'',percent:'',"phone-call":'',"phone-forwarded":'',"phone-incoming":'',"phone-missed":'',"phone-off":'',"phone-outgoing":'',phone:'',"pie-chart":'',"play-circle":'',play:'',"plus-circle":'',"plus-square":'',plus:'',pocket:'',power:'',printer:'',radio:'',"refresh-ccw":'',"refresh-cw":'',repeat:'',rewind:'',"rotate-ccw":'',"rotate-cw":'',rss:'',save:'',scissors:'',search:'',send:'',server:'',settings:'',"share-2":'',share:'',"shield-off":'',shield:'',"shopping-bag":'',"shopping-cart":'',shuffle:'',sidebar:'',"skip-back":'',"skip-forward":'',slack:'',slash:'',sliders:'',smartphone:'',smile:'',speaker:'',square:'',star:'',"stop-circle":'',sun:'',sunrise:'',sunset:'',tablet:'',tag:'',target:'',terminal:'',thermometer:'',"thumbs-down":'',"thumbs-up":'',"toggle-left":'',"toggle-right":'',"trash-2":'',trash:'',trello:'',"trending-down":'',"trending-up":'',triangle:'',truck:'',tv:'',twitter:'',type:'',umbrella:'',underline:'',unlock:'',"upload-cloud":'',upload:'',"user-check":'',"user-minus":'',"user-plus":'',"user-x":'',user:'',users:'',"video-off":'',video:'',voicemail:'',"volume-1":'',"volume-2":'',"volume-x":'',volume:'',watch:'',"wifi-off":'',wifi:'',wind:'',"x-circle":'',"x-octagon":'',"x-square":'',x:'',youtube:'',"zap-off":'',zap:'',"zoom-in":'',"zoom-out":''}},function(e){e.exports={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"}},function(e,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var l=Object.assign||function(e){for(var n=1;n2&&void 0!==arguments[2]?arguments[2]:[];!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,e),this.name=n,this.contents=i,this.tags=t,this.attrs=l({},o.default,{class:"feather feather-"+n})}return t(e,[{key:"toSvg",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return""+this.contents+""}},{key:"toString",value:function(){return this.contents}}]),e}();n.default=c},function(e,n,i){"use strict";var l=o(i(8)),t=o(i(31)),r=o(i(30));function o(e){return e&&e.__esModule?e:{default:e}}e.exports={icons:l.default,toSvg:t.default,replace:r.default}},function(e,n,i){var l=i(0)("iterator"),t=!1;try{var r=[7][l]();r.return=function(){t=!0},Array.from(r,function(){throw 2})}catch(e){}e.exports=function(e,n){if(!n&&!t)return!1;var i=!1;try{var r=[7],o=r[l]();o.next=function(){return{done:i=!0}},r[l]=function(){return o},e(r)}catch(e){}return i}},function(e,n,i){var l=i(22),t=i(0)("toStringTag"),r="Arguments"==l(function(){return arguments}());e.exports=function(e){var n,i,o;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(i=function(e,n){try{return e[n]}catch(e){}}(n=Object(e),t))?i:r?l(n):"Object"==(o=l(n))&&"function"==typeof n.callee?"Arguments":o}},function(e,n,i){var l=i(38),t=i(0)("iterator"),r=i(10);e.exports=i(2).getIteratorMethod=function(e){if(void 0!=e)return e[t]||e["@@iterator"]||r[l(e)]}},function(e,n,i){"use strict";var l=i(6),t=i(12);e.exports=function(e,n,i){n in e?l.f(e,n,t(0,i)):e[n]=i}},function(e,n,i){var l=i(10),t=i(0)("iterator"),r=Array.prototype;e.exports=function(e){return void 0!==e&&(l.Array===e||r[t]===e)}},function(e,n,i){var l=i(5);e.exports=function(e,n,i,t){try{return t?n(l(i)[0],i[1]):n(i)}catch(n){var r=e.return;throw void 0!==r&&l(r.call(e)),n}}},function(e,n,i){"use strict";var l=i(24),t=i(28),r=i(17),o=i(42),a=i(41),c=i(21),y=i(40),p=i(39);t(t.S+t.F*!i(37)(function(e){Array.from(e)}),"Array",{from:function(e){var n,i,t,h,x=r(e),s="function"==typeof this?this:Array,u=arguments.length,d=u>1?arguments[1]:void 0,f=void 0!==d,v=0,g=p(x);if(f&&(d=l(d,u>2?arguments[2]:void 0,2)),void 0==g||s==Array&&a(g))for(i=new s(n=c(x.length));n>v;v++)y(i,v,f?d(x[v],v):x[v]);else for(h=g.call(x),i=new s;!(t=h.next()).done;v++)y(i,v,f?o(h,d,[t.value,v],!0):t.value);return i.length=v,i}})},function(e,n,i){var l=i(3),t=i(17),r=i(9)("IE_PROTO"),o=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=t(e),l(e,r)?e[r]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?o:null}},function(e,n,i){var l=i(1).document;e.exports=l&&l.documentElement},function(e,n,i){var l=i(15),t=Math.max,r=Math.min;e.exports=function(e,n){return(e=l(e))<0?t(e+n,0):r(e,n)}},function(e,n,i){var l=i(23),t=i(21),r=i(46);e.exports=function(e){return function(n,i,o){var a,c=l(n),y=t(c.length),p=r(o,y);if(e&&i!=i){for(;y>p;)if((a=c[p++])!=a)return!0}else for(;y>p;p++)if((e||p in c)&&c[p]===i)return e||p||0;return!e&&-1}}},function(e,n,i){var l=i(22);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==l(e)?e.split(""):Object(e)}},function(e,n,i){var l=i(3),t=i(23),r=i(47)(!1),o=i(9)("IE_PROTO");e.exports=function(e,n){var i,a=t(e),c=0,y=[];for(i in a)i!=o&&l(a,i)&&y.push(i);for(;n.length>c;)l(a,i=n[c++])&&(~r(y,i)||y.push(i));return y}},function(e,n,i){var l=i(49),t=i(19);e.exports=Object.keys||function(e){return l(e,t)}},function(e,n,i){var l=i(6),t=i(5),r=i(50);e.exports=i(4)?Object.defineProperties:function(e,n){t(e);for(var i,o=r(n),a=o.length,c=0;a>c;)l.f(e,i=o[c++],n[i]);return e}},function(e,n,i){var l=i(5),t=i(51),r=i(19),o=i(9)("IE_PROTO"),a=function(){},c=function(){var e,n=i(26)("iframe"),l=r.length;for(n.style.display="none",i(45).appendChild(n),n.src="javascript:",(e=n.contentWindow.document).open(),e.write(" + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+
+ +

My own small public place

+ + +
+ + +
+ + + + + + + + + + + + + +
+ + + diff --git a/posts/arch-repo/index.html b/posts/arch-repo/index.html new file mode 100644 index 0000000..d765fbe --- /dev/null +++ b/posts/arch-repo/index.html @@ -0,0 +1,267 @@ + + + + + + + + + + + Own Arch Linux Repository + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

Own Arch Linux Repository

+
+ + Published by @ultradesu + + on 2020-07-14 + + +
+
+ + + +
+

Prerequisites

+
    +
  • Ubuntu Server with Nginx and Docker
  • +
+
+

Creating repository

+

Repository database is managed via repo-add script bundled with Arch Linux pacman package manager. Since pacman is not available in Ubuntu repository I use docker archlinux image for managing repository. This guide assumes that repository located in /srv/arch-repo. First of all move all your packages into /srv/arch-repo. Following command will create or update repository database.

+
REPO_URL=repo.sun.hexor.ru
+REPO_PATH=/srv/arch-repo
+docker run -v ${REPO_PATH}:/repo --rm archlinux \
+bash -c "repo-add /repo/${REPO_URL}.db.tar.gz /repo/*pkg.tar.zst"
+
+

Important aspect

+
    +
  • Name of the database should be REPO_URL.db.tar.gz, in this case REPO_URL is repo.sun.hexor.ru.
  • +
+
+

Periodically database repo update

+

I use systemd:

+
# Service unit
+# /etc/systemd/system/update-arch-repo.service
+[Unit]
+Description=Updating arch linux repository database for %I
+Requires=docker.service
+
+[Service]
+ExecStart=/usr/bin/docker run -v /srv/arch-repo:/repo --rm archlinux bash -c "repo-add /repo/%i.db.tar.gz /repo/*pkg.tar.zst"
+
+[Install]
+WantedBy=multi-user.target
+
+
# Timer unit
+# /etc/systemd/system/update-arch-repo.timer
+[Unit]
+Description=Schedule arch repo database update for %I
+
+[Timer]
+# every 15 minutes
+OnCalendar=*:0/15
+
+[Install]
+WantedBy=timers.target
+
+

Activate timer:

+
REPO_URL=repo.sun.hexor.ru
+systemctl enable update-arch-repo@${REPO_URL}.timer
+
+

Reverse proxy for HTTPS access

+

I use NGINX

+
server {
+    server_name repo.sun.hexor.ru;
+    listen [::]:443 ssl;
+    listen 443 ssl;
+    include security.conf; # my security options
+    include letsencrypt.conf; # my ssl config. 
+    root /srv/arch-repo;
+    location / {
+        autoindex on;
+        try_files $uri $uri/ =404;
+    }
+    access_log /var/log/nginx/logs/repo.sun.hexor.ru.access.log custom;
+    error_log /var/log/nginx/logs/repo.sun.hexor.ru.error.log;
+}
+
+

Configure repo on your machines

+

Add your repo to /etc/pacman.conf:

+
[repo.sun.hexor.ru]
+Server = https://repo.sun.hexor.ru
+
+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/htpasswd/index.html b/posts/htpasswd/index.html new file mode 100644 index 0000000..592a06f --- /dev/null +++ b/posts/htpasswd/index.html @@ -0,0 +1,204 @@ + + + + + + + + + + + .htpasswd one-liner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

.htpasswd one-liner

+
+ + Published by @ultradesu + + on 2020-07-13 + + +
+
+ + + +
+

It's annoying when you need apache2-utils just for creating password hash for Basic auth. So here is Shell one-liner doing it using openssl.

+
user=ab
+pass=pwd
+printf "${user}:$(openssl passwd -apr1 ${pass})\n"
+
+
+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/index.html b/posts/index.html new file mode 100644 index 0000000..a6d2b2e --- /dev/null +++ b/posts/index.html @@ -0,0 +1,228 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

All articles

+ + + + + + + + + + + + +
+ + + diff --git a/posts/japan-visa/index.html b/posts/japan-visa/index.html new file mode 100644 index 0000000..fd0d6e0 --- /dev/null +++ b/posts/japan-visa/index.html @@ -0,0 +1,275 @@ + + + + + + + + + + + Multiple-Entry Visa to Japan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

Multiple-Entry Visa to Japan

+
+ + Published by @ultradesu + + on 2025-05-15 + + +
+
+ + + +
+

✈️ 🇯🇵 Multiple-Entry Visa Overview

+
    +
  • Processing Time: 5–7 business days
  • +
  • Fee: Free of charge for Russian citizens
  • +
  • Validity: Typically up to 3 years
  • +
+

To be eligible for a multiple-entry visa to Japan:

+
    +
  • You must have visited Japan at least once in the past 3 years
  • +
  • You must be able to demonstrate sufficient financial means to support travel
  • +
+

🗓️ Default Stay Duration & Pro Tip

+

Even with a multiple-entry visa, the default allowed stay is usually 15 days per visit.
+However, if your first trip is longer than 15 days, immigration may automatically grant you a longer stay period:

+
    +
  • First trip over 15 days → future stays up to 30 days
  • +
  • First trip over 30 days → future stays may allow up to 90 days
  • +
+

Just make sure your travel itinerary reflects the longer stay for the first visit.

+
+

This guide is based on personal experience applying from Cyprus and Russia. The process is generally similar in other countries.

+
+
+

Required Documents

+

Submit all documents in the following order. Embassies do not help rearrange papers during submission.

+
    +
  1. Valid Passport
  2. +
  3. Proof of Legal Stay +
      +
    • Cyprus: Cyprus Residence Permit
    • +
    • Russia: Internal (domestic) passport
    • +
    +
  4. +
  5. Two Photos (35×45 mm)
  6. +
  7. Two Visa Application Forms (form link)
  8. +
  9. Statement of Purpose (why you need a multiple-entry visa)
  10. +
  11. Proof of Financial Capability +
      +
    • 3 months of bank statements
    • +
    • Employment certificate with annual income
    • +
    • Savings or investment documents
    • +
    +
  12. +
  13. Detailed Travel Itinerary (template)
  14. +
  15. Round-Trip Flight Reservation
  16. +
  17. Hotel Booking Confirmation
  18. +
  19. Proof of Eligibility +
      +
    • Past visits to Japan (within 3 years)
    • +
    • Employment + financial stability
    • +
    +
  20. +
+
+

You must meet at least one:
+① Recent short-term visit to Japan
+② Stable job and sufficient income

+
+
+

Document Examples

+ +
+

Procedure

+

1. Prepare Documents

+

Gather and fill out all required documents in advance. Appointments are often available within a few days, especially in Cyprus.

+

2. Book Appointment by Email

+

Send a request by email to the local consulate. You can also ask questions about your case or required documents.

+
+

Contacts

+

Embassy in Cyprus

+

🌐 Visa Page
+📧 cy-ryouji@cy.mofa.go.jp +📞 +357 22 394 800

+

Consulate in Khabarovsk

+

🌐 Visa Page
+📧 ryojibu@kh.mofa.go.jp
+📞 +7 (4212) 41-30-48

+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/mikrotik-tailscale/index.html b/posts/mikrotik-tailscale/index.html new file mode 100644 index 0000000..3fd4e9e --- /dev/null +++ b/posts/mikrotik-tailscale/index.html @@ -0,0 +1,282 @@ + + + + + + + + + + + Tailscale on Mikrotik containers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

Tailscale on Mikrotik containers

+
+ + Published by @ultradesu + + on 2025-10-03 + + +
+
+ + + +
+
+

Create a tag in Tailscale

+

Open Visual ACLs → Tags and create a tag (e.g. tag:mikrotik-lms). We’ll assign this tag via container args so your ACLs/policies apply to the node.

+ +
+

Create an OAuth client (auth_keys scope)

+

Create an OAuth client with the auth_keys scope. You’ll use the client secret to mint auth keys via API (do not put the OAuth secret directly into the container).

+ +
+

Storage on usb1 (container root + state)

+

Put both the container’s root storage and Tailscale state on usb1 to avoid filling the internal flash.

+
# Point RouterOS container system to usb1 for all image/layer data.
+/container/config/set root-dir=/usb1/container tmpdir=/usb1/container/tmp
+/file/make-dir usb1/container/tmp
+
+# Create a persistent state dir for Tailscale on usb1.
+/file/make-dir usb1/tailscale-state
+
+
+

Make sure usb1 is mounted and has enough free space. The destination path of the mount must match TS_STATE_DIR (/var/lib/tailscale).

+
+
+

Environment variables (RouterOS env list)

+

Required: TS_AUTHKEY, TS_STATE_DIR, and --advertise-tags matching your ACL tag. Optional vars go after.

+
# --- REQUIRED ---
+/container/envs/add name=TAILSCALE_VARS key=TS_AUTHKEY   value="tskey-REPLACE_ME" \
+  comment="Headless auth key; do not use the raw OAuth secret"
+
+/container/envs/add name=TAILSCALE_VARS key=TS_STATE_DIR value="/var/lib/tailscale" \
+  comment="Persistent state dir inside container; must match the bind mount dst"
+
+/container/envs/add name=TAILSCALE_VARS key=TS_EXTRA_ARGS \
+  value="--advertise-tags=tag:mikrotik-lms" \
+  comment="Attach the policy tag so ACLs apply"
+
+# --- OPTIONAL ---
+/container/envs/add name=TAILSCALE_VARS key=TS_ROUTES        value="10.0.5.0/24" \
+  comment="Advertise routed subnet(s) if acting as a subnet router"
+
+/container/envs/add name=TAILSCALE_VARS key=TS_ENABLE_METRICS value="true" \
+  comment="Expose /debug/metrics for Prometheus"
+
+/container/envs/add name=TAILSCALE_VARS key=TS_ACCEPT_DNS     value="true" \
+  comment="Accept MagicDNS/control-plane DNS"
+
+/container/envs/add name=TAILSCALE_VARS key=TS_USERSPACE      value="false" \
+  comment="Kernel mode if TUN available; set true to force userspace"
+
+
+

Create the mount and veth, then the container (pinned image)

+

Mount from usb1 to the same path as TS_STATE_DIR. Create a veth for networking. Pin the image tag (don’t use latest).

+
# --- MOUNT ON usb1 (matches TS_STATE_DIR) ---
+/container/mounts/add name=TS_state src=/usb1/tailscale-state dst=/var/lib/tailscale
+
+# --- VETH FOR CONTAINER NETWORKING ---
+/interface/veth/add name=veth-tailscaled address=172.31.0.2/24 gateway=172.31.0.1
+/ip/address/add address=172.31.0.1/24 interface=veth-tailscaled
+
+# --- CONTAINER (PINNED VERSION) ---
+# Replace tag with a current one from Docker Hub.
+/container/add name=tailscaled \
+  remote-image=tailscale/tailscale:v1.76.0 \
+  envlist=TAILSCALE_VARS \
+  mounts=TS_state \
+  interfaces=veth-tailscaled \
+  start-on-boot=yes
+
+/container/start tailscaled
+
+image +

Reference docs:

+ +
+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/openwrt-shadowsocks/index.html b/posts/openwrt-shadowsocks/index.html new file mode 100644 index 0000000..29fd5a1 --- /dev/null +++ b/posts/openwrt-shadowsocks/index.html @@ -0,0 +1,267 @@ + + + + + + + + + + + Shadowsocks on OpenWRT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

Shadowsocks on OpenWRT

+
+ + Published by @ultradesu + + on 2025-06-16 + + +
+
+ + + +
+

Shadowsocks-libev + OpenWRT + Hardware Switch on GL.iNet

+

1. Install packages

+
opkg update
+opkg install \
+  luci-app-shadowsocks-libev \
+  shadowsocks-libev-ss-redir \
+  shadowsocks-libev-config
+
+
+

2. Add server + redir instance

+
SERVER_NAME='Bulgaria'
+SERVER_ADDRESS='1.1.1.1'
+SERVER_PORT=38583
+SERVER_PROTO='chacha20-ietf-poly1305'
+SERVER_PASS='YoUr_pASS'
+LOCAL_PORT=12345
+
+uci set shadowsocks-libev.$SERVER_NAME=server
+uci set shadowsocks-libev.$SERVER_NAME.server="$SERVER_ADDRESS"
+uci set shadowsocks-libev.$SERVER_NAME.server_port="$SERVER_PORT"
+uci set shadowsocks-libev.$SERVER_NAME.method="$SERVER_PROTO"
+uci set shadowsocks-libev.$SERVER_NAME.password="$SERVER_PASS"
+
+uci set shadowsocks-libev.VPN_redir=ss_redir
+uci set shadowsocks-libev.VPN_redir.disabled='0'
+uci set shadowsocks-libev.VPN_redir.mode='tcp_and_udp'
+uci set shadowsocks-libev.VPN_redir.fast_open='1'
+uci set shadowsocks-libev.VPN_redir.no_delay='1'
+uci set shadowsocks-libev.VPN_redir.reuse_port='1'
+uci set shadowsocks-libev.VPN_redir.server="$SERVER_NAME"
+uci set shadowsocks-libev.VPN_redir.local_port="$LOCAL_PORT"
+
+
+

3. Enable switch

+
uci set switch-button.@main[0].func='shadowsocks'
+uci commit
+
+

Create /etc/gl-switch.d/shadowsocks.sh:

+
#!/bin/sh
+action=$1
+port=12345
+chain=SHADOWSOCKS
+
+if [ "$action" = "on" ]; then
+    # Start ss-redir service
+    /etc/init.d/shadowsocks-libev start
+
+    # Add iptables rules
+    iptables -t nat -N $chain 2>/dev/null
+    iptables -t nat -F $chain
+    iptables -t nat -A $chain -d 192.168.0.0/16 -j RETURN
+    iptables -t nat -A $chain -p tcp -j REDIRECT --to-ports $port
+    iptables -t nat -A PREROUTING -i br-lan -p tcp -j $chain
+
+    # Drop existing connections
+    conntrack -F
+else
+    # Delete iptables rules
+    iptables -t nat -D PREROUTING -i br-lan -p tcp -j $chain
+    iptables -t nat -F $chain
+    iptables -t nat -X $chain
+
+    # Stop ss-redir service
+    /etc/init.d/shadowsocks-libev stop
+fi
+
+
chmod +x /etc/gl-switch.d/shadowsocks.sh
+
+

Now you can enable Shadowsocks VPN using hardware switch on router. Also it's possible to start and stop VPN by running /etc/gl-switch.d/shadowsocks.sh on/off

+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/private-vpn/index.html b/posts/private-vpn/index.html new file mode 100644 index 0000000..290cad8 --- /dev/null +++ b/posts/private-vpn/index.html @@ -0,0 +1,259 @@ + + + + + + + + + + + Private WireGuard telegram bot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

Private WireGuard telegram bot

+
+ + Published by @ultradesu + + on 2023-08-25 + + +
+
+ + + +
+

Wireguard-Peer-Manager

+

image

+

That bot can add Wireguard peers to config, reload it and send client config back via Telegram.

+

FYI: That tool stores client private keys into server config as comments.

+

How to use:

+
# create initial wg config or use your own.
+# P.S. Keep in mind that WPM can't manage peers created manually
+# due to absence of client private key.
+
+export CONFIG=$(cat <<-END
+[Interface]
+Address = 10.150.200.1/24
+ListenPort = 51820
+PrivateKey = $(wg genkey)
+PostUp = iptables -A FORWARD -i %i -o %i -j ACCEPT
+PostDown = iptables -D FORWARD -i %i -o %i -j ACCEPT
+SaveConfig = false
+END
+)
+
+sudo -E bash -c 'cat > /etc/wireguard/private.conf << EOF
+${CONFIG}
+EOF
+'
+
+cd /etc/wiregurad
+sudo git clone https://github.com/house-of-vanity/Wireguard-Peer-Manager wpm
+cd wpm
+
+# install python and system requirements.
+apt install qrencode python3-pip
+pip3 install -r requirements.txt
+
+# Create config
+cp wpm_example.conf wpm.conf
+
+# CLI usage. Client configs saved into `clients/peer_name.{conf,-qr.png,-qr.txt}`
+python3 gen.py --peer my-pc   # add a new peer `my-pc`
+python3 gen.py --delete my-pc # delete peer `my-pc`
+python3 gen.py --update       # just regenerate all configs in `clients/`
+python3 gen.py --json         # show WG status in JSON
+
+# Telegram bot usage
+TG_TOKEN=1292121488:AAG... TG_ADMIN=<comma separated list of usernames> python3 bot.py
+
+
+

Config

+ + + + + +
KeyDefaultDescription
allowed_ips0.0.0.0allowed_ips for generated peer configs.
dns8.8.8.8DNS for peer configs
hostname$(hostname -f):51820server address for peer configs. May be an IP.
configwg0WireGuard config to work with.
+

Telegram Interface

+

drawing drawing

+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/qemu/index.html b/posts/qemu/index.html new file mode 100644 index 0000000..5d0a0fc --- /dev/null +++ b/posts/qemu/index.html @@ -0,0 +1,252 @@ + + + + + + + + + + + KVM/QEMU self hosted hypervisor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

KVM/QEMU self hosted hypervisor

+
+ + Published by @ultradesu + + on 2020-07-14 + + +
+
+ + + +
+

Requirements

+
    +
  • Ubuntu Linux server (tested on 18.04 and 20.04)
  • +
  • CPU with virtualisation enabled
  • +
+
+

Installing

+

Installing VT staff

+
sudo apt install qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils
+
+

I'd like to assign IPs for my VMs in the same network as server.

+

Here is netplan config:

+
# /etc/netplan/00-installer-config.yaml
+network:
+  ethernets:
+    enp2s0f0:
+      dhcp4: false
+      dhcp6: false
+  bridges:
+    br0:
+      interfaces: [enp2s0f0]
+      dhcp4: true
+      dhcp6: true
+  version: 2
+
+

Generate and apply network config:

+
sudo netplan generate
+sudo netplan --debug apply
+
+# Check bridge
+sudo networkctl
+IDX LINK       TYPE     OPERATIONAL SETUP
+  1 lo         loopback carrier     unmanaged
+  2 enp2s0f0   ether    enslaved    configured
+  3 br0        bridge   routable    configured
+  4 virbr0     bridge   no-carrier  unmanaged
+  5 virbr0-nic ether    off         unmanaged
+
+# Check DHCP lease on new bridge
+sudo ip a 
+2: enp2s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
+    link/ether xxx brd ff:ff:ff:ff:ff:ff
+4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
+    link/ether xxx brd ff:ff:ff:ff:ff:ff
+    inet 192.168.88.28/24 brd 192.168.88.255 scope global dynamic br0
+       valid_lft 535sec preferred_lft 535sec
+
+
+

Managing VMs

+

Grant permissions to use virtmanager to your user on server:

+
sudo adduser $USER libvirt-qemu
+sudo adduser $USER libvirt
+
+

Use virt-manager GUI utility on client or virsh CLI tool for managing VMs and data pools.

+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/run-arm64-vm-on-amd64/index.html b/posts/run-arm64-vm-on-amd64/index.html new file mode 100644 index 0000000..939c849 --- /dev/null +++ b/posts/run-arm64-vm-on-amd64/index.html @@ -0,0 +1,267 @@ + + + + + + + + + + + Run arm64 VM on amd64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

Run arm64 VM on amd64

+
+ + Published by @ultradesu + + on 2024-10-12 + + +
+
+ + + +
+

Install QEMU

+
sudo apt install qemu-system-arm
+
+

Create necessary support files

+

Next, create a VM-specific flash volume for storing NVRAM variables, which are necessary when booting EFI firmware:

+
truncate -s 64m varstore.img
+truncate -s 64m efi.img
+dd if=/usr/share/qemu-efi-aarch64/QEMU_EFI.fd of=efi.img conv=notrunc
+
+

Fetch the Ubuntu cloud image

+

You need to fetch the ARM64 variant of the Ubuntu cloud image you would like to use in the virtual machine. You can go to the official Ubuntu cloud image website, select the Ubuntu release, and then download the variant whose filename ends in -arm64.img. For example, if you want to use the latest Jammy cloud image, you should download the file named jammy-server-cloudimg-arm64.img.

+

Run QEMU natively on an ARM64 host

+

If you have access to an ARM64 host, you should be able to create and launch an ARM64 virtual machine there. Note that the command below assumes that you have already set up a network bridge to be used by the virtual machine.

+
sudo qemu-system-aarch64 \
+ -enable-kvm \
+ -m 1024 \
+ -cpu host \
+ -M virt \
+ -nographic \
+ -drive if=pflash,format=raw,file=efi.img,readonly=on \
+ -drive if=pflash,format=raw,file=varstore.img \
+ -drive if=none,file=jammy-server-cloudimg-arm64.img,id=hd0 \
+ -device virtio-blk-device,drive=hd0 -netdev type=tap,id=net0 \
+ -device virtio-net-device,netdev=net0
+
+

Run an emulated ARM64 VM on x86

+

You can also emulate an ARM64 virtual machine on an x86 host. To do that:

+
sudo qemu-system-aarch64 \
+ -m 2048 \
+ -cpu max \
+ -M virt \
+ -nographic \
+ -drive if=pflash,format=raw,file=efi.img,readonly=on \
+ -drive if=pflash,format=raw,file=varstore.img \
+ -drive if=none,file=jammy-server-cloudimg-arm64.img,id=hd0 \
+ -device virtio-blk-device,drive=hd0 \
+ -netdev type=tap,id=net0 \
+ -device virtio-net-device,netdev=net0
+
+

To set default password for image

+
sudo apt-get install cloud-image-utils
+
+cat >user-data <<EOF
+#cloud-config
+password: ubuntu
+chpasswd: { expire: False }
+ssh_pwauth: True
+EOF
+
+cloud-localds user-data.img user-data
+
+# user-data.img MUST come after the rootfs. 
+sudo qemu-system-aarch64 \
+ -m 2048 \
+ -cpu max \
+ -M virt \
+ -nographic \
+ -drive if=pflash,format=raw,file=efi.img,readonly=on \
+ -drive if=pflash,format=raw,file=varstore.img \
+ -drive if=none,file=jammy-server-cloudimg-arm64.img,id=hd0 \
+ -drive file=user-data.img,format=raw \ 
+ -device virtio-blk-device,drive=hd0 \
+ -netdev type=tap,id=net0 \
+ -device virtio-net-device,netdev=net0
+
+
+
+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/stunnel-tls/index.html b/posts/stunnel-tls/index.html new file mode 100644 index 0000000..75cc729 --- /dev/null +++ b/posts/stunnel-tls/index.html @@ -0,0 +1,226 @@ + + + + + + + + + + + Expose service via TLS stunnel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

Expose service via TLS stunnel

+
+ + Published by @ultradesu + + on 2023-12-18 + + +
+
+ + + +
+

First of all, I encountered an issue with the Outline VPN server, which exposes Prometheus metrics on 127.0.0.1 with no option to change it. As a solution, I used stunnel4. Essentially, it works as a TLS proxy, listening on a configured port and forwarding traffic to another.

+

[Server1 (stunnel server)] <==> [Server2 (stunnel client)]

+

Server side

+

Install stunnel and create configs:

+
ab@cy:/etc/stunnel$ cat outline_prom.conf
+debug = 5
+output = /var/log/stunnel.log
+
+[outline_prom]
+accept = 0.0.0.0:9095
+connect = 127.0.0.1:9092
+PSKsecrets = /etc/stunnel/psk.txt
+
+

psk.txt is a credentials file and looks like:

+
# I used `openssl rand -hex 32` to generate secret
+ab@cy:/etc/stunnel$ cat psk.txt
+user:secret_string
+
+

Client side

+

psk.txt the same and config looks like:

+
ab@home:/etc/stunnel$ cat /etc/stunnel/outline_prom.conf
+[outline_prom_cy]
+client = yes
+accept = 0.0.0.0:9095
+connect = cy.hexor.cy:9095
+PSKsecrets = /etc/stunnel/psk.txt
+
+
+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/torrent/index.html b/posts/torrent/index.html new file mode 100644 index 0000000..d36a204 --- /dev/null +++ b/posts/torrent/index.html @@ -0,0 +1,293 @@ + + + + + + + + + + + qBittornt web via VPN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

qBittornt web via VPN

+
+ + Published by @ultradesu + + on 2023-08-25 + + +
+
+ + + +
+

Requirements

+
    +
  • Ubuntu Linux server (tested on 18.04 and 20.04)
  • +
  • NGINX
  • +
  • Wireguard VPN config (easy to change to any other vpn)
  • +
+
+

Installing

+

Install qbittorrent-nox for headless qBittorent package:

+
sudo apt install -y qbittorrent-nox
+
+

Configuring VPN Network Namespace

+

Create /usr/bin/torrent_ns script and make it exucutable. It configures Network Namespace for qBittorent.

+
VPN_CFG_NAME=torrent
+VPN_COMMAND="wg-quick up ${VPN_CFG_NAME}"
+export SCRIPT=$(cat <<-END
+#!/bin/bash
+ip netns del torrent
+sleep 2
+ip netns add torrent
+ip link add veth0 type veth peer name veth1
+ip link set veth1 netns torrent
+ip address add 10.99.99.1/24 dev veth0
+ip netns exec torrent ip address add 10.99.99.2/24 dev veth1
+ip link set dev veth0 up
+ip netns exec torrent ip link set dev veth1 up
+ip netns exec torrent ip route add default via 10.99.99.1
+mkdir -p /etc/netns/torrent
+echo nameserver 8.8.8.8 > /etc/netns/torrent/resolv.conf
+sleep 3
+ip netns exec torrent ${VPN_COMMAND}
+sleep 3
+ip netns exec torrent sudo -u ${USER} qbittorrent-nox
+END
+)
+
+sudo -E bash -c 'cat > /usr/bin/torrent_ns << EOF
+${SCRIPT}
+EOF
+'
+
+sudo chmod +x /usr/bin/torrent_ns
+
+

Systemd Autostart

+

Systemd unit to enable autostart:

+
export SERVICE=$(cat <<-END
+[Unit]
+Description=qBittorrent via vpn
+After=network.target
+StartLimitIntervalSec=0
+
+[Service]
+Type=simple
+Restart=always
+RestartSec=1
+User=root
+ExecStart=/usr/bin/torrent_ns
+ExecStop=/usr/bin/ip netns del torrent
+END
+)
+
+sudo -E bash -c 'cat > /etc/systemd/system/qbittorrent.service << EOF
+${SERVICE}
+EOF
+'
+
+sudo systemctl enable --now qbittorrent.service
+
+

Nginx Reverse Proxy

+
# /etc/nginx/sites-enabled/tr.hexor.cy.conf 
+server {
+        listen 443 ssl http2;
+        server_name tr.hexor.ru;
+        include ssl.conf; # my own ssl config
+        location / {
+                proxy_pass http://10.99.99.2:8080;
+                proxy_set_header Host $host;
+                proxy_set_header X-Real-IP $remote_addr;
+                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+                proxy_set_header X-Forwarded-Proto $scheme;
+                proxy_hide_header   Referer;
+                proxy_hide_header   Origin;
+                proxy_set_header    Referer                 '';
+                proxy_set_header    Origin                  '';
+        }
+}
+server {
+        listen 80;
+        server_name tr.hexor.cy;
+        listen [::]:80;
+        return 302 https://$host$request_uri;
+}
+
+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/wg-over-udp2raw/index.html b/posts/wg-over-udp2raw/index.html new file mode 100644 index 0000000..21eeb45 --- /dev/null +++ b/posts/wg-over-udp2raw/index.html @@ -0,0 +1,345 @@ + + + + + + + + + + + WireGuard over udp2raw + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

WireGuard over udp2raw

+
+ + Published by @ultradesu + + on 2024-10-25 + + +
+
+ + + +
+

Running WireGuard over udp2raw

+

Introduction

+

In certain network environments, establishing a direct WireGuard connection may be challenging due to firewalls, NAT restrictions, or ISPs blocking UDP traffic. udp2raw provides a solution by encapsulating WireGuard's UDP traffic into encrypted packets that mimic TCP or ICMP protocols. This method helps bypass UDP blocking and can make your VPN connection appear as regular TCP or ICMP traffic. Method described is almost the same as TLS tunnel using stunnel but faster in my tests and works with UDP as well as with TCP.

+

Prerequisites

+
    +
  • Server: A remote server with root access where WireGuard is installed and configured.
  • +
  • Client: A local machine with root access where WireGuard is installed and configured.
  • +
  • udp2raw: Downloaded on both the server and client from the udp2raw releases page.
  • +
  • A shared secret key: A plain text string used by udp2raw for authentication (e.g., SecReT-StrinG).
  • +
+

How It Works

+
[WireGuard Client]
+    |
+    | UDP traffic to 127.0.0.1:6666
+    v
++---------------------+
+| udp2raw Client      |
+| Listening on:       |
+| 127.0.0.1:6666      |
+| Connecting to:      |
+| SERVER_IP:7777      |
++---------------------+
+    |
+    | Encrypted UDP/TCP/ICMP packets to SERVER_IP:7777
+    v
+~~~~~~~~~~~~~ Internet ~~~~~~~~~~~~~
+    |
+    v
++---------------------+
+| udp2raw Server      |
+| Listening on:       |
+| 0.0.0.0:7777        |
+| Forwarding to:      |
+| 127.0.0.1:51820     |
++---------------------+
+    |
+    | UDP traffic to 127.0.0.1:51820
+    v
+[WireGuard Server]
+
+

Data Flow

+
    +
  1. WireGuard Client sends UDP packets to 127.0.0.1:6666, which is the local udp2raw Client.
  2. +
  3. udp2raw Client encapsulates these UDP packets into encrypted UDP/TCP/ICMP packets and sends them over the internet to SERVER_IP:7777 (the udp2raw Server).
  4. +
  5. udp2raw Server listens on 0.0.0.0:7777, decrypts the incoming packets, and forwards them as UDP packets to 127.0.0.1:51820 (the WireGuard Server).
  6. +
  7. WireGuard Server processes the packets and sends responses back through the same path in reverse.
  8. +
+

Steps

+

1. Download and Install udp2raw

+

On both the server and client:

+
    +
  1. +

    Navigate to the udp2raw releases page.

    +
  2. +
  3. +

    Download the appropriate binary for your system (e.g., udp2raw_amd64 for 64-bit Linux).

    +
  4. +
  5. +

    Make the binary executable and move it to a directory in your $PATH:

    +
    chmod +x udp2raw_amd64
    +sudo mv udp2raw_amd64 /usr/local/bin/
    +
    +
  6. +
+

2. Configure udp2raw on the Server

+

Create a systemd service to run udp2raw as a daemon.

+

Command Explanation

+
    +
  • -s: Run in server mode.
  • +
  • -l 0.0.0.0:7777: Listen on all interfaces on port 7777.
  • +
  • -r 127.0.0.1:51820: Forward packets to 127.0.0.1 on port 51820 (WireGuard listens here).
  • +
  • -k <PLAIN_TEXT_SECRET>: Use the provided key for authentication.
  • +
  • --raw-mode udp: Use UDP mode for raw sockets.
  • +
  • -a: Auto-adjust TCP options.
  • +
+

Create Systemd Service

+

Create a file /etc/systemd/system/udp2raw.service with the following content:

+
[Unit]
+Description=udp2raw Server
+After=network.target
+
+[Service]
+ExecStart=/usr/local/bin/udp2raw_amd64 -s -l 0.0.0.0:7777 -r 127.0.0.1:51820 -k SecReT-StrinG --raw-mode udp -a
+Restart=always
+User=root
+RestartSec=3
+
+[Install]
+WantedBy=multi-user.target
+
+

Start the Service

+
sudo systemctl enable --now udp2raw
+
+

3. Configure udp2raw on the Client

+

Command Explanation

+
    +
  • -c: Run in client mode.
  • +
  • -l 127.0.0.1:6666: Listen on local address 127.0.0.1 on port 6666 (WireGuard will connect here).
  • +
  • -r SERVER_IP:7777: Connect to the udp2raw server at SERVER_IP on port 7777.
  • +
  • -k <PLAIN_TEXT_SECRET>: Use the same key as the server for authentication.
  • +
  • --raw-mode udp: Use UDP mode for raw sockets.
  • +
  • -a: Auto-adjust TCP options.
  • +
+

Create Systemd Service

+

Replace SERVER_IP with your server's IP address.

+

Create a file /etc/systemd/system/udp2raw.service with the following content:

+
[Unit]
+Description=udp2raw Client
+After=network.target
+
+[Service]
+ExecStart=/usr/local/bin/udp2raw_amd64 -c -l 127.0.0.1:6666 -r SERVER_IP:7777 -k SecReT-StrinG --raw-mode udp -a
+Restart=always
+User=root
+RestartSec=3
+
+[Install]
+WantedBy=multi-user.target
+
+

Start the Service

+
sudo systemctl enable --now udp2raw
+
+

4. Configure WireGuard to Use udp2raw

+

On the client, modify your WireGuard configuration to connect to the local udp2raw port.

+

Example WireGuard Client Configuration

+
[Interface]
+PrivateKey = <Client_Private_Key>
+Address = 10.0.0.2/32
+DNS = 8.8.8.8
+
+[Peer]
+PublicKey = <Server_Public_Key>
+Endpoint = 127.0.0.1:6666
+AllowedIPs = 0.0.0.0/0
+PersistentKeepalive = 25
+
+
    +
  • Endpoint: Set to 127.0.0.1:6666, the local udp2raw client's listening address.
  • +
  • AllowedIPs: Set to 0.0.0.0/0 to route all traffic through the VPN, or specify desired subnets.
  • +
+

Conclusion

+

By wrapping WireGuard traffic with udp2raw, you can bypass network restrictions that prevent standard UDP traffic. This setup encapsulates your VPN traffic in a way that appears as regular TCP, UDP or ICMP packets, enhancing connectivity in restrictive environments.

+

References

+ + +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/posts/wg-xray/index.html b/posts/wg-xray/index.html new file mode 100644 index 0000000..744d9a7 --- /dev/null +++ b/posts/wg-xray/index.html @@ -0,0 +1,386 @@ + + + + + + + + + + + WireGuard over Xray VLESS Protocol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + +
+
+
+

WireGuard over Xray VLESS Protocol

+
+ + Published by @ultradesu + + on 2024-10-04 + + +
+
+ + + +
+

Setting Up Xray with WireGuard over Reality Protocol

+

In this guide, we'll walk through the steps to set up Xray-core to proxy WireGuard traffic using the Reality protocol over TCP. This configuration can help bypass network restrictions and enhance privacy.

+

Installing Xray-core

+

Install the latest beta version of Xray-core with root privileges:

+
sudo bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install --beta -u root
+
+

Generating Configurations

+

First, generate the necessary keys and IDs:

+
# Generate X25519 keys using Xray's built-in command
+_x25519=$(xray x25519)
+PRIVATE_KEY=$(echo "$_x25519" | awk -F': ' '/Private key/{print $2}')
+PUBLIC_KEY=$(echo "$_x25519" | awk -F': ' '/Public key/{print $2}')
+
+# Generate a unique UUID for the client
+CLIENT_UUID=$(uuidgen)
+
+# Generate a random short ID
+SHORT_IDS=$(openssl rand -hex 8)
+
+# Define server address and port
+SERVER_ADDRESS="k8s.hexor.cy"
+PORT=8443
+
+

Server Configuration

+

Create the server configuration file server.json:

+
# /usr/local/etc/xray/config.json
+cat > server.json <<EOF
+{
+    "log": {
+        "loglevel": "warning"
+    },
+    "inbounds": [
+        {
+            "listen": "0.0.0.0",
+            "port": ${PORT},
+            "protocol": "vless",
+            "settings": {
+                "clients": [
+                    {
+                        "id": "${CLIENT_UUID}",
+                        "flow": ""
+                    }
+                ],
+                "decryption": "none"
+            },
+            "streamSettings": {
+                "network": "tcp",
+                "security": "reality",
+                "realitySettings": {
+                    "show": false,
+                    "dest": "www.google.com:443",
+                    "xver": 0,
+                    "serverNames": [
+                        "www.google.com"
+                    ],
+                    "privateKey": "${PRIVATE_KEY}",
+                    "shortIds": [
+                        "${SHORT_IDS}"
+                    ]
+                }
+            }
+        }
+    ],
+    "outbounds": [
+        {
+            "protocol": "freedom",
+            "tag": "direct"
+        }
+    ]
+}
+EOF
+
+

This configuration sets up an inbound VLESS listener over TCP with Reality security, using the generated private key and short IDs.

+

Client Configuration

+

Create the client configuration file client.json:

+
# /usr/local/etc/xray/config.json
+cat > client.json <<EOF
+{
+    "log": {
+        "loglevel": "warning"
+    },
+    "inbounds": [
+        {
+            "tag": "wireguard",
+            "port": 6666,
+            "protocol": "dokodemo-door",
+            "settings": {
+                "address": "127.0.0.1",
+                "port": 6666,
+                "network": "udp"
+            }
+        }
+    ],
+    "outbounds": [
+        {
+            "protocol": "vless",
+            "settings": {
+                "vnext": [
+                    {
+                        "address": "${SERVER_ADDRESS}",
+                        "port": ${PORT},
+                        "users": [
+                            {
+                                "id": "${CLIENT_UUID}",
+                                "encryption": "none",
+                                "flow": ""
+                            }
+                        ]
+                    }
+                ]
+            },
+            "streamSettings": {
+                "network": "tcp",
+                "security": "reality",
+                "realitySettings": {
+                    "show": false,
+                    "fingerprint": "chrome",
+                    "serverName": "www.google.com",
+                    "publicKey": "${PUBLIC_KEY}",
+                    "shortId": "${SHORT_IDS}",
+                    "spiderX": ""
+                }
+            },
+            "tag": "proxy"
+        }
+    ]
+}
+EOF
+
+

This client configuration captures local UDP traffic (from WireGuard) and forwards it to the Xray server using the VLESS protocol with Reality security.

+

Example WireGuard Setup

+

Server Configuration

+

Set up WireGuard on the server:

+
# Server configuration: /etc/wireguard/homenet.conf
+[Interface]
+Address = 10.0.0.1/24
+ListenPort = 6666
+PrivateKey = <server_private_key>
+PostUp = iptables -A FORWARD -i %i -o %i -j ACCEPT
+PostDown = iptables -D FORWARD -i %i -o %i -j ACCEPT
+SaveConfig = false
+MTU = 1300
+
+[Peer]
+PublicKey = <peer_public_key>
+AllowedIPs = 10.0.0.2/32
+Endpoint = 127.0.0.1:6666  # Local UDP port proxied by Xray
+PersistentKeepalive = 10
+
+

Client Configuration

+

Set up WireGuard on the client:

+
# Client configuration: /etc/wireguard/wg0.conf
+[Interface]
+Address = 10.0.0.2/24
+PrivateKey = <client_private_key>
+MTU = 1300
+
+[Peer]
+PublicKey = <server_public_key>
+AllowedIPs = 10.0.0.0/24
+Endpoint = 127.0.0.1:6666  # Local UDP port proxied by Xray
+PersistentKeepalive = 10
+
+

In this setup, WireGuard traffic is sent to a local port (6666), which is proxied by Xray over the Reality protocol to the server.

+

Routing a Single Client's Traffic through the VPN on Mikrotik

+

To route a specific client's traffic through the VPN using a Mikrotik router, follow these steps:

+
    +
  1. +

    Create a New Routing Table:

    +
    /routing table add fib name=vpn
    +
    +

    This command creates a new routing table named vpn, which will be used to direct traffic through the VPN interface.

    +
  2. +
  3. +

    Mark Routing for the Specific Client:

    +
    /ip firewall mangle add action=mark-routing chain=prerouting new-routing-mark=vpn passthrough=yes src-address=192.168.90.234
    +
    +

    This firewall mangle rule marks all traffic originating from the client with IP address 192.168.90.234. The new-routing-mark=vpn ensures that packets from this client use the vpn routing table.

    +
  4. +
  5. +

    Add a Route in the VPN Routing Table:

    +
    /ip route add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=homenet routing-table=vpn
    +
    +

    This adds a default route (0.0.0.0/0) to the vpn routing table, directing marked traffic to the homenet gateway (which should be the VPN interface).

    +
  6. +
+ +
+ + + + + +
+
+ + + + + + + + + +
+ + + diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..302a59c --- /dev/null +++ b/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: +Allow: / +Sitemap: //btwiusearch.net/sitemap.xml diff --git a/screenshot/screenshot-dark.png b/screenshot/screenshot-dark.png new file mode 100644 index 0000000..3c1c9e0 Binary files /dev/null and b/screenshot/screenshot-dark.png differ diff --git a/screenshot/screenshot-light.png b/screenshot/screenshot-light.png new file mode 100644 index 0000000..9192747 Binary files /dev/null and b/screenshot/screenshot-light.png differ diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..30a8b11 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,121 @@ + + + + //btwiusearch.net/ + + + //btwiusearch.net/about/ + 2023-08-25 + + + //btwiusearch.net/page/1/ + + + //btwiusearch.net/page/2/ + + + //btwiusearch.net/posts/ + + + //btwiusearch.net/posts/arch-repo/ + 2020-07-14 + + + //btwiusearch.net/posts/htpasswd/ + 2020-07-13 + + + //btwiusearch.net/posts/japan-visa/ + 2025-05-15 + + + //btwiusearch.net/posts/mikrotik-tailscale/ + 2025-10-03 + + + //btwiusearch.net/posts/openwrt-shadowsocks/ + 2025-06-16 + + + //btwiusearch.net/posts/private-vpn/ + 2023-08-25 + + + //btwiusearch.net/posts/qemu/ + 2020-07-14 + + + //btwiusearch.net/posts/run-arm64-vm-on-amd64/ + 2024-10-12 + + + //btwiusearch.net/posts/stunnel-tls/ + 2023-12-18 + + + //btwiusearch.net/posts/torrent/ + 2023-08-25 + + + //btwiusearch.net/posts/wg-over-udp2raw/ + 2024-10-25 + + + //btwiusearch.net/posts/wg-xray/ + 2024-10-04 + + + //btwiusearch.net/tags/ + + + //btwiusearch.net/tags/arm64/ + + + //btwiusearch.net/tags/containers/ + + + //btwiusearch.net/tags/kvm/ + + + //btwiusearch.net/tags/linux/ + + + //btwiusearch.net/tags/network/ + + + //btwiusearch.net/tags/networking/ + + + //btwiusearch.net/tags/nginx/ + + + //btwiusearch.net/tags/openwrt/ + + + //btwiusearch.net/tags/qemu/ + + + //btwiusearch.net/tags/selfhosting/ + + + //btwiusearch.net/tags/tools/ + + + //btwiusearch.net/tags/torrent/ + + + //btwiusearch.net/tags/travel/ + + + //btwiusearch.net/tags/virtualization/ + + + //btwiusearch.net/tags/vless/ + + + //btwiusearch.net/tags/vpn/ + + + //btwiusearch.net/tags/wireguard/ + + diff --git a/tags/arm64/index.html b/tags/arm64/index.html new file mode 100644 index 0000000..76a6da5 --- /dev/null +++ b/tags/arm64/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "arm64"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/containers/index.html b/tags/containers/index.html new file mode 100644 index 0000000..9bb02d1 --- /dev/null +++ b/tags/containers/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "containers"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 0000000..a93edaf --- /dev/null +++ b/tags/index.html @@ -0,0 +1,268 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +

All tags

+ + + + + + + + + + + +
+ + + diff --git a/tags/kvm/index.html b/tags/kvm/index.html new file mode 100644 index 0000000..be9c2b0 --- /dev/null +++ b/tags/kvm/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "kvm"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/linux/index.html b/tags/linux/index.html new file mode 100644 index 0000000..7edccb6 --- /dev/null +++ b/tags/linux/index.html @@ -0,0 +1,224 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "linux"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/network/index.html b/tags/network/index.html new file mode 100644 index 0000000..db5d294 --- /dev/null +++ b/tags/network/index.html @@ -0,0 +1,179 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "network"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/networking/index.html b/tags/networking/index.html new file mode 100644 index 0000000..825d5b2 --- /dev/null +++ b/tags/networking/index.html @@ -0,0 +1,179 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "networking"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/nginx/index.html b/tags/nginx/index.html new file mode 100644 index 0000000..d972e5e --- /dev/null +++ b/tags/nginx/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "nginx"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/openwrt/index.html b/tags/openwrt/index.html new file mode 100644 index 0000000..6ee15cf --- /dev/null +++ b/tags/openwrt/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "openwrt"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/qemu/index.html b/tags/qemu/index.html new file mode 100644 index 0000000..2d9f179 --- /dev/null +++ b/tags/qemu/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "qemu"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/selfhosting/index.html b/tags/selfhosting/index.html new file mode 100644 index 0000000..c4f6cce --- /dev/null +++ b/tags/selfhosting/index.html @@ -0,0 +1,199 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "selfhosting"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/tools/index.html b/tags/tools/index.html new file mode 100644 index 0000000..3115688 --- /dev/null +++ b/tags/tools/index.html @@ -0,0 +1,184 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "tools"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/torrent/index.html b/tags/torrent/index.html new file mode 100644 index 0000000..ed7f384 --- /dev/null +++ b/tags/torrent/index.html @@ -0,0 +1,179 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "torrent"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/travel/index.html b/tags/travel/index.html new file mode 100644 index 0000000..7bc75ca --- /dev/null +++ b/tags/travel/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "travel"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/virtualization/index.html b/tags/virtualization/index.html new file mode 100644 index 0000000..acb9bba --- /dev/null +++ b/tags/virtualization/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "virtualization"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/vless/index.html b/tags/vless/index.html new file mode 100644 index 0000000..3a48245 --- /dev/null +++ b/tags/vless/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "vless"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/vpn/index.html b/tags/vpn/index.html new file mode 100644 index 0000000..35ed463 --- /dev/null +++ b/tags/vpn/index.html @@ -0,0 +1,184 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "vpn"

+ + + + + + + + + + + + + +
+ + + diff --git a/tags/wireguard/index.html b/tags/wireguard/index.html new file mode 100644 index 0000000..5bfca30 --- /dev/null +++ b/tags/wireguard/index.html @@ -0,0 +1,184 @@ + + + + + + + + + + + btwiusearch.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + +

Entries tagged - "wireguard"

+ + + + + + + + + + + + + +
+ + +