<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Iván Moreno</title>
    <description>The latest articles on DEV Community by Iván Moreno (@ivanmoreno).</description>
    <link>https://dev.to/ivanmoreno</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F367044%2Fef8e0d7a-499f-4e15-ab08-b7cc864aba33.jpg</url>
      <title>DEV Community: Iván Moreno</title>
      <link>https://dev.to/ivanmoreno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ivanmoreno"/>
    <language>en</language>
    <item>
      <title>How to setup a remote development environment with code-server and nextcloud</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Wed, 09 Feb 2022 19:07:03 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-setup-a-remote-development-environment-with-code-server-and-nextcloud-2a1g</link>
      <guid>https://dev.to/ivanmoreno/how-to-setup-a-remote-development-environment-with-code-server-and-nextcloud-2a1g</guid>
      <description>&lt;p&gt;In this tutorial we are going to setup a complete remote work environment with the ability to sync our workspace directory across multiple devices using &lt;code&gt;nextcloud&lt;/code&gt; and &lt;code&gt;code-server&lt;/code&gt; as web editor. &lt;/p&gt;

&lt;p&gt;We can use this work environment if we need to use a powerful computer using a cloud server or just to keep our environment from anywhere at any time on the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;In this tutorial you need to have the following components&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A kubernetes cluster (I recommend to use &lt;a href="https://k3s.io" rel="noopener noreferrer"&gt;k3s.io&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A nextcloud installation (you can install via &lt;a href="https://github.com/nextcloud/helm" rel="noopener noreferrer"&gt;helm&lt;/a&gt; within the same k8s cluster)&lt;/li&gt;
&lt;li&gt;A k8s storage class where you can save your files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All kubernetes manifest files are stored in &lt;a href="https://github.com/ivanmorenoj/code-server-nextcloud" rel="noopener noreferrer"&gt;this&lt;/a&gt; repository feel free to clone and customize&lt;/p&gt;

&lt;h2&gt;
  
  
  System Architecture
&lt;/h2&gt;

&lt;p&gt;This is the system architecture used in this tutorial&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru8qh9dro2xb2rtz6b9p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru8qh9dro2xb2rtz6b9p.png" alt="architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are going to use a kubernetes storage class to save our files and share between &lt;code&gt;code-server&lt;/code&gt; and &lt;code&gt;nc-client&lt;/code&gt; deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure nextcloud sync client
&lt;/h2&gt;

&lt;p&gt;In order to sync all out files across multiple devices we are going to use &lt;code&gt;nextcloud&lt;/code&gt; as sync system, in this tutorial we used the &lt;code&gt;nextcloudcmd&lt;/code&gt; command to sync our files using a docker container.&lt;/p&gt;

&lt;p&gt;The docker used syncs the nextcloud remote directory every X seconds, you need to set the &lt;code&gt;NC_USER&lt;/code&gt;, &lt;code&gt;NC_PASS&lt;/code&gt; and &lt;code&gt;NC_HOST&lt;/code&gt; in the &lt;code&gt;k8s/conf/nextcloud-client-conf.yaml&lt;/code&gt; file, the &lt;code&gt;NC_PASS&lt;/code&gt; is a secret file, so you'll need to encode as &lt;code&gt;base64&lt;/code&gt; (example: &lt;code&gt;echo -n 'verysecretpass' | base64&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Create the Persistent Volume Claim for nextcloud client&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/01-pvc-nextcloud-client.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create the environment variables for the &lt;code&gt;nc-client&lt;/code&gt; container&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/conf/nextcloud-client-conf.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create the &lt;code&gt;nc-client&lt;/code&gt; deployment &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/conf/nextcloud-client-conf.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This container will sync the files in the nextcloud server every 300 seconds&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure vscode on the server
&lt;/h2&gt;

&lt;p&gt;In this tutorial we are using the &lt;code&gt;linuxserver/code-server&lt;/code&gt; which includes the web version of visual studio code (oss version) and is highly customizable due to &lt;code&gt;s6-overlay&lt;/code&gt; system. This docker image allow us to extend the capabilities of the base image using &lt;a href="https://github.com/linuxserver/docker-mods" rel="noopener noreferrer"&gt;docker mods&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can setup your environment creating your own docker mod, a docker mod can bootstrap your environment and install your required packages such as kubectl, helm, awscli, etc. &lt;a href="https://github.com/ivanmorenoj/lsio-mods" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is an example of my docker mod used to bootstrap my work environment, this mod install the required packages and bootstrap the config files in the container.&lt;/p&gt;

&lt;p&gt;If you want to setup your own docker mod I highly recommend to check the &lt;a href="https://github.com/linuxserver/docker-mods" rel="noopener noreferrer"&gt;docker-mods&lt;/a&gt; documentation for more info.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker mods
&lt;/h3&gt;

&lt;p&gt;In this tutorial I'm using my own docker mod, &lt;a href="https://github.com/linuxserver/docker-mods" rel="noopener noreferrer"&gt;this&lt;/a&gt; docker mod install the required packages such as psql, awscli, python, kubectl, helm, zsh, etc. This docker mod also bootstrap the config files such a gitconfig, aws credentials, zshrc file, ssh keys, kube config file, etc. This files are mounted in the &lt;code&gt;code-server&lt;/code&gt; pod then the bootstrap scrip will copy these files in her location with the correct owner and permissions.&lt;/p&gt;

&lt;p&gt;We are using the &lt;code&gt;linuxserver/mods:code-server-extension-arguments&lt;/code&gt; to install the required vscode extensions in the &lt;code&gt;code-server&lt;/code&gt; pod. The docker mods can be set in the &lt;code&gt;DOCKE_MODS&lt;/code&gt; variable separated by &lt;code&gt;|&lt;/code&gt;. Check the list of official mods for &lt;a href="https://mods.linuxserver.io/?mod=code-server" rel="noopener noreferrer"&gt;code-server&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConfigMap&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;code-server-configmap&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prod&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;DOCKER_MODS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;linuxserver/mods:code-server-extension-arguments|ghcr.io/ivanmorenoj/lsio-mods:code-server-ws"&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Configure code-server on k8s
&lt;/h3&gt;

&lt;p&gt;Create the Persistent Volume Claim for code-server deployment&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/02-pvc-code-server.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configure the &lt;code&gt;code-server&lt;/code&gt; values such the user and sudo password, the docker mods and the config files.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/conf/code-server-conf.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create the &lt;code&gt;code-server&lt;/code&gt; deployment, you can modify the resource request and limits according to your available compute resources&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/04-code-server.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Configure the ingress
&lt;/h2&gt;

&lt;p&gt;In this step we are going to setup the ingress in order to access to our &lt;code&gt;code-server&lt;/code&gt; installation through a &lt;em&gt;FQDN&lt;/em&gt; domain with TLS endpoint.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/05-ingress.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;NOTE: Make sure you have pointed your domain to your k8s cluster and configured your firewall to access to your installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;When you finished the setup you'll have a remote environment with your files synchronized in a remote server with nextcloud just like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvwgyfst1feceko919zw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvwgyfst1feceko919zw.jpg" alt="code-server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can edit, test and build your projects in your browser from anywhere at anytime, you only need a stable internet connection and a web browser.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Understand how linux containers works with practical examples</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Sun, 18 Apr 2021 06:02:41 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/understand-how-linux-containers-works-with-practical-examples-2ng2</link>
      <guid>https://dev.to/ivanmoreno/understand-how-linux-containers-works-with-practical-examples-2ng2</guid>
      <description>&lt;p&gt;Nowadays a bast majority of server workloads run using linux containers because of his flexibility and lightweight but have you ever think how does linux containers works. In this tutorial we will demystify how does linux containers works with some practical examples. Linux containers works thanks two kernel features: &lt;code&gt;namespaces&lt;/code&gt; and &lt;code&gt;cgroups&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Linux Namespaces&lt;/li&gt;
&lt;li&gt;Linux control groups (cgroups)&lt;/li&gt;
&lt;li&gt;
Container Fundamentals (key technologies)

&lt;ul&gt;
&lt;li&gt;Process namespace fundamentals&lt;/li&gt;
&lt;li&gt;Filesystem Overlay FS fundamentals&lt;/li&gt;
&lt;li&gt;Networking Linux bridge fundamentals&lt;/li&gt;
&lt;li&gt;Control groups (cgroups) fundamentals&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create a container from scratch&lt;/li&gt;
&lt;li&gt;
Inspect Namespaces within a docker container

&lt;ul&gt;
&lt;li&gt;Install docker CE&lt;/li&gt;
&lt;li&gt;Inspect Docker Network&lt;/li&gt;
&lt;li&gt;Inspect cgroups in a docker container&lt;/li&gt;
&lt;li&gt;Inspect overlay fs in a docker container&lt;/li&gt;
&lt;li&gt;Inspect docker process namespace&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Linux Namespaces
&lt;/h1&gt;

&lt;p&gt;A namespace wraps a global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource.  Changes to the global resource are visible to other processes that are members of the namespace, but are invisible to other processes. One use of namespaces is to implement containers. [&lt;a href="https://man7.org/linux/man-pages/man7/namespaces.7.html"&gt;1&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Currently the linux kernel have 8 types of namespaces:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Namespace&lt;/th&gt;
&lt;th&gt;Isolates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cgroup&lt;/td&gt;
&lt;td&gt;Cgroup root directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPC&lt;/td&gt;
&lt;td&gt;System V IPC, POSIX message queues&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;Network devices, stacks, ports, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mount&lt;/td&gt;
&lt;td&gt;Mount points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PID&lt;/td&gt;
&lt;td&gt;Process IDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time&lt;/td&gt;
&lt;td&gt;Boot and monotonic clocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;User and group IDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UTS&lt;/td&gt;
&lt;td&gt;Hostname and NIS domain name&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Linux control groups (cgroups)
&lt;/h1&gt;

&lt;p&gt;Cgroups allow you to allocate resources — such as CPU time, system memory, network bandwidth, or combinations of these resources — among user-defined groups of tasks (processes) running on a system. You can monitor the cgroups you configure, deny cgroups access to certain resources, and even reconfigure your cgroups dynamically on a running system. [&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/ch01"&gt;2&lt;/a&gt;]&lt;/p&gt;

&lt;h1&gt;
  
  
  Container Fundamentals (key technologies)
&lt;/h1&gt;

&lt;p&gt;In this section we gonna make some practices with the following key technologies that make possible the usage of containers in linux:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process namespace fundamentals&lt;/li&gt;
&lt;li&gt;Filesystem Overlay FS fundamentals&lt;/li&gt;
&lt;li&gt;Networking Linux bridge fundamentals&lt;/li&gt;
&lt;li&gt;Control groups (cgroups) fundamentals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NOTE: &lt;strong&gt;&lt;em&gt;This tutorial was made using a VM with 1GB of ram and 1vCPU using debian 10 buster with kernel &lt;code&gt;4.19.0-16-amd64&lt;/code&gt;. All commands were executed using &lt;code&gt;root&lt;/code&gt; privileges&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Process namespace fundamentals
&lt;/h2&gt;

&lt;p&gt;A process namespace isolate a running command from the host. Let's see how to implement a process namespace in linux.&lt;/p&gt;

&lt;p&gt;List  process namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lsns &lt;span class="nt"&gt;-t&lt;/span&gt; pid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the PID of the current terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$$&lt;/span&gt; &lt;span class="c"&gt;# parent PID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch a new zsh terminal using namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;unshare &lt;span class="nt"&gt;--fork&lt;/span&gt; &lt;span class="nt"&gt;--pid&lt;/span&gt; &lt;span class="nt"&gt;--mount-proc&lt;/span&gt; zsh
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;300 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;300 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;300 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;300 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;300 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;top
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the process tree from the parent&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ps f &lt;span class="nt"&gt;-g&lt;/span&gt; &amp;lt;PPID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lsns &lt;span class="nt"&gt;-t&lt;/span&gt; pid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Filesystem Overlay FS fundamentals
&lt;/h2&gt;

&lt;p&gt;Containers need tohave a filesystem, one of the most used filesystem for containers is &lt;code&gt;overlay&lt;/code&gt; who can mount with &lt;code&gt;layers&lt;/code&gt; and merge in a single directory, the lower layers are read only and all changes are made on the upper layer. Let's see how does overlay fs works.&lt;/p&gt;

&lt;p&gt;Create directories&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;lower1,lower2,upper,work,merged&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create some files in lower directories&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Lower 1 - original"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; lower1/file1.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Lower 2 - original"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; lower2/file2.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create overlay FS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; overlay &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;lowerdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/lower1:/tmp/lower2,upperdir&lt;span class="o"&gt;=&lt;/span&gt;/tmp/upper,workdir&lt;span class="o"&gt;=&lt;/span&gt;/tmp/work none /tmp/merged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create, modify files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp/merged
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"file created in merged directory"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; file_created.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"file 1 modified"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; file1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Umount overlay fs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp
&lt;span class="nv"&gt;$ &lt;/span&gt;umount /tmp/merged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect lower and upper dirs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;find &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.txt'&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f 2&amp;gt;/dev/null | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;fn&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;&amp;gt; cat &lt;/span&gt;&lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Networking Linux bridge fundamentals
&lt;/h2&gt;

&lt;p&gt;Linux container uses network namespaces to isolate the network from the host, this is possible implementing a bridge interface that acts like network switch, and every container connect to that interface with his own ip address. Let's see how does linux bridge and network namespaces works.&lt;/p&gt;

&lt;p&gt;Create a Network Virtual bridge&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;add br-net &lt;span class="nb"&gt;type &lt;/span&gt;bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List Network Interfaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign an IP Address to bridge interface&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip addr add 192.168.55.1/24 brd + dev br-net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bring UP the bridge interface&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-net up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create 2 Network Namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns add ns1
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns add ns2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a Virtual Ethernet cable pair&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;add veth-ns1 &lt;span class="nb"&gt;type &lt;/span&gt;veth peer name br-ns1
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;add veth-ns2 &lt;span class="nb"&gt;type &lt;/span&gt;veth peer name br-ns2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign veth to namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;veth-ns1 netns ns1
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;veth-ns2 netns ns2
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-ns1 master br-net
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-ns2 master br-net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign IP address to veth within namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns1 addr add 192.168.55.2/24 dev veth-ns1
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns2 addr add 192.168.55.3/24 dev veth-ns2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bring UP veth interfaces within Namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns1 &lt;span class="nb"&gt;link set &lt;/span&gt;lo up
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns2 &lt;span class="nb"&gt;link set &lt;/span&gt;lo up
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns1 &lt;span class="nb"&gt;link set &lt;/span&gt;veth-ns1 up
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns2 &lt;span class="nb"&gt;link set &lt;/span&gt;veth-ns2 up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bring UP bridge veth in the local host&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-ns1 up
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-ns2 up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure default route within namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns1 route add default via 192.168.55.1 dev veth-ns1 
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; ns2 route add default via 192.168.55.1 dev veth-ns2 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable IP forward in the host&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sysctl &lt;span class="nt"&gt;-w&lt;/span&gt; net.ipv4.ip_forward&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure &lt;code&gt;MASQUERADE&lt;/code&gt; in the host for &lt;code&gt;192.168.55.0/24&lt;/code&gt; subnet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; POSTROUTING &lt;span class="nt"&gt;-s&lt;/span&gt; 192.168.55.0/24 &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; br-net &lt;span class="nt"&gt;-j&lt;/span&gt; MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check connectivity within namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns &lt;span class="nb"&gt;exec &lt;/span&gt;ns1 ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 192.168.55.3 &lt;span class="c"&gt;# ping ns2&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns &lt;span class="nb"&gt;exec &lt;/span&gt;ns2 ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 192.168.55.2 &lt;span class="c"&gt;# ping ns1&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns &lt;span class="nb"&gt;exec &lt;/span&gt;ns1 ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 192.168.55.1 &lt;span class="c"&gt;# ping br-net gateway&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns &lt;span class="nb"&gt;exec &lt;/span&gt;ns2 ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 192.168.55.1 &lt;span class="c"&gt;# ping br-net gateway&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns &lt;span class="nb"&gt;exec &lt;/span&gt;ns1 ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 1.1.1.1 &lt;span class="c"&gt;# ping internet&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns &lt;span class="nb"&gt;exec &lt;/span&gt;ns2 ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 1.1.1.1 &lt;span class="c"&gt;# ping internet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Control groups (cgroups) fundamentals
&lt;/h2&gt;

&lt;p&gt;Control groups or cgroups are used by containers to limit the usage of resource in the host machine. Let's see how does cgroups works.&lt;/p&gt;

&lt;p&gt;Create cgroups directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mycg/&lt;span class="o"&gt;{&lt;/span&gt;memory,cpusets,cpu&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mount cgroups directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; cgroup &lt;span class="nt"&gt;-o&lt;/span&gt; memory none /mycg/memory
&lt;span class="nv"&gt;$ &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; cgroup &lt;span class="nt"&gt;-o&lt;/span&gt; cpu,cpuacct none /mycg/cpu
&lt;span class="nv"&gt;$ &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; cgroup &lt;span class="nt"&gt;-o&lt;/span&gt; cpuset none /mycg/cpusets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create new directories under CPU controller&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mycg/cpu/user&lt;span class="o"&gt;{&lt;/span&gt;1..3&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign CPU shares to every user (This example uses 1vCPU)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 2048 / (2048 + 512 + 80) = 77%&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;2048 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /mycg/cpu/user1/cpu.shares
&lt;span class="c"&gt;# 512 / (2048 + 512 + 80) = 19%&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;512 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /mycg/cpu/user2/cpu.shares
&lt;span class="c"&gt;# 80 / (2048 + 512 + 80) = 3%&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;80 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /mycg/cpu/user3/cpu.shares
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create artificial load&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /dev/urandom &amp;amp;&amp;gt; /dev/null &amp;amp;
&lt;span class="nv"&gt;$ PID1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /dev/urandom &amp;amp;&amp;gt; /dev/null &amp;amp;
&lt;span class="nv"&gt;$ PID2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /dev/urandom &amp;amp;&amp;gt; /dev/null &amp;amp;
&lt;span class="nv"&gt;$ PID3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign process to every user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PID1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /mycg/cpu/user1/tasks
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PID2&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /mycg/cpu/user2/tasks
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PID3&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /mycg/cpu/user3/tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Monitoring process&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;top
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Create a container from scratch
&lt;/h1&gt;

&lt;p&gt;So far we know how does linux namespaces works, now lets create a container using overlayfs, network namespaces, cgroups and process namespaces from scratch. Let's see how a linux container is created. &lt;/p&gt;

&lt;p&gt;Download and extract debian container fs from docker&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker pull debian
&lt;span class="nv"&gt;$ &lt;/span&gt;docker save debian &lt;span class="nt"&gt;-o&lt;/span&gt; debian.tar
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;debian_layer
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; fs/&lt;span class="o"&gt;{&lt;/span&gt;lower,upper,work,merged&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tar &lt;/span&gt;xf debian.tar &lt;span class="nt"&gt;-C&lt;/span&gt; debian_layer
&lt;span class="nv"&gt;$ &lt;/span&gt;find debian_layer &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'layer.tar'&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;tar &lt;/span&gt;xf &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; fs/lower &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create bridge interface&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns add cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;add br-cnt &lt;span class="nb"&gt;type &lt;/span&gt;bridge
&lt;span class="nv"&gt;$ &lt;/span&gt;ip addr add 192.168.22.1/24 brd + dev br-cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-cnt up
&lt;span class="nv"&gt;$ &lt;/span&gt;sysctl &lt;span class="nt"&gt;-w&lt;/span&gt; net.ipv4.ip_forward&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nv"&gt;$ &lt;/span&gt;iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-I&lt;/span&gt; POSTROUTING 1 &lt;span class="nt"&gt;-s&lt;/span&gt; 192.168.22.0/24 &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; br-cnt &lt;span class="nt"&gt;-j&lt;/span&gt; MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create overlay Filesystem from debian container fs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mount &lt;span class="nt"&gt;-vt&lt;/span&gt; overlay &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;lowerdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./fs/lower,upperdir&lt;span class="o"&gt;=&lt;/span&gt;./fs/upper,workdir&lt;span class="o"&gt;=&lt;/span&gt;./fs/work none ./fs/merged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mounting Virtual File Systems&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mount &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;--bind&lt;/span&gt; /dev ./fs/merged/dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch process namespace within &lt;code&gt;fs/merged&lt;/code&gt; fs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;unshare &lt;span class="nt"&gt;--fork&lt;/span&gt; &lt;span class="nt"&gt;--pid&lt;/span&gt; &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/run/netns/cnt &lt;span class="nb"&gt;chroot&lt;/span&gt; ./fs/merged &lt;span class="se"&gt;\&lt;/span&gt;
    /usr/bin/env &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/bin:/usr/bin:/sbin:/usr/sbin &lt;span class="nv"&gt;TERM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TERM&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    /bin/bash &lt;span class="nt"&gt;--login&lt;/span&gt; +h
&lt;span class="c"&gt;# Mount proc within container&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;mount &lt;span class="nt"&gt;-vt&lt;/span&gt; proc proc /proc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect the container with &lt;code&gt;br-cnt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;add veth-cnt &lt;span class="nb"&gt;type &lt;/span&gt;veth peer name br-veth-cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;veth-cnt netns cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-veth-cnt master br-cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;br-veth-cnt up
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; cnt addr add 192.168.22.2/24 dev veth-cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; cnt &lt;span class="nb"&gt;link set &lt;/span&gt;lo up
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; cnt &lt;span class="nb"&gt;link set &lt;/span&gt;veth-cnt up
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; cnt route add default via 192.168.22.1 dev veth-cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns &lt;span class="nb"&gt;exec &lt;/span&gt;cnt ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 1.1.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mount cgroup&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /sys/fs/cgroup/memory/cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;10000000 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /sys/fs/cgroup/memory/cnt/memory.limit_in_bytes
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;0 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /sys/fs/cgroup/memory/cnt/memory.swappiness
&lt;span class="nv"&gt;$ CHILD_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsns &lt;span class="nt"&gt;-t&lt;/span&gt; pid | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"[/]bin/bash --login +h"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $4}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CHILD_PID&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /sys/fs/cgroup/memory/cnt/tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run commands within container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apt update
&lt;span class="nv"&gt;$ &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx procps curl &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;nginx
&lt;span class="nv"&gt;$ &lt;/span&gt;curl 127.0.0.1:80
&lt;span class="nv"&gt;$ &lt;/span&gt;curl 192.168.22.2:80 &lt;span class="c"&gt;# from host&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt; &amp;lt;/dev/zero &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 15m&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;15&lt;span class="o"&gt;)&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean all&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;umount /proc &lt;span class="c"&gt;# within container&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="c"&gt;# within container&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;umount &lt;span class="nt"&gt;-R&lt;/span&gt; ./fs/merged
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;del br-veth-cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;del br-cnt
&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns del cnt &lt;span class="c"&gt;# grep cnt /proc/mounts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Inspect Namespaces within a docker container
&lt;/h1&gt;

&lt;p&gt;Fortunately for us there is a program that simplifies the usage of containers, for us this program is &lt;code&gt;docker&lt;/code&gt; who manage the life-cycle of running a container. Let's see how does &lt;code&gt;docker&lt;/code&gt; implement the namespaces running a container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install docker CE
&lt;/h2&gt;

&lt;p&gt;Install docker community edition from official script in &lt;a href="https://get.docker.com"&gt;get.docker.com&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://get.docker.com &lt;span class="nt"&gt;-o&lt;/span&gt; install_docker.sh
&lt;span class="nv"&gt;$ &lt;/span&gt;less install_docker.sh &lt;span class="c"&gt;# optional&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sh install_docker.sh
&lt;span class="nv"&gt;$ &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;newgrp docker &lt;span class="c"&gt;# Or logout and login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inspect Docker Network
&lt;/h2&gt;

&lt;p&gt;Create a bridge network using docker&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network create mynet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect bridge network, see subnet using IP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ BR_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;ip &lt;span class="nb"&gt;link&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'@'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/br-/{gsub(":",""); print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ip addr show &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BR_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect Docker bridge network, see subnet using docker&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network inspect mynet | &lt;span class="nb"&gt;grep &lt;/span&gt;Subnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run an nginx web server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; nginx &lt;span class="nt"&gt;--net&lt;/span&gt; mynet &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect network namespace from &lt;code&gt;nginx&lt;/code&gt; container&lt;/p&gt;

&lt;p&gt;Create symlink from &lt;code&gt;/proc&lt;/code&gt; to &lt;code&gt;/var/run/netns&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ CONTAINER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;docker container ps | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/nginx/{print $1}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ CONTAINER_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;docker inspect &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{.State.Pid}}'&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/run/netns/
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-sfT&lt;/span&gt; /proc/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_PID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/ns/net /var/run/netns/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check network interface within namespace&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip netns list
&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;link &lt;/span&gt;show eth0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check IP address of nginx container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; addr show eth0
&lt;span class="nv"&gt;$ &lt;/span&gt;docker container inspect nginx | &lt;span class="nb"&gt;grep &lt;/span&gt;IPAddress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check port forwarding from 8080 to 80&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-nvL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inspect cgroups in a docker container
&lt;/h2&gt;

&lt;p&gt;Run a Ubuntu container with limited resources&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; test_cg &lt;span class="nt"&gt;--memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10m &lt;span class="nt"&gt;--cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.1 &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See cgroup fs hierarchy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ CONTAINER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;docker container ps &lt;span class="nt"&gt;--no-trunc&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/test_cg/{print $1}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;tree /sys/fs/cgroup/&lt;span class="o"&gt;{&lt;/span&gt;memory,cpu&lt;span class="o"&gt;}&lt;/span&gt;/docker/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See attached task to container cgroup&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container top test_cg | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $2}'&lt;/span&gt; &lt;span class="c"&gt;# container parent PID&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /sys/fs/cgroup/&lt;span class="o"&gt;{&lt;/span&gt;memory,cpu&lt;span class="o"&gt;}&lt;/span&gt;/docker/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/tasks &lt;span class="c"&gt;# the same as container parent PID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Monitoring the container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container stats test_cg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate CPU load&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /dev/urandom &amp;amp;&amp;gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate Memory load&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt; &amp;lt;/dev/zero &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 50m&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;30&lt;span class="o"&gt;)&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inspect overlay fs in a docker container
&lt;/h2&gt;

&lt;p&gt;Run a ubuntu container with limited resources&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; test_overlayfs &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; debian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: &lt;strong&gt;&lt;em&gt;The merged layer is the actual container Filesystem&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Inspect lower layers with tree and less&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container inspect test_overlayfs &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{.GraphDriver.Data.LowerDir}}'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'BEGIN{FS=":"}{for (i=1; i&amp;lt;= NF; i++) print $i}'&lt;/span&gt; | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;low&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;tree &lt;span class="nt"&gt;-L&lt;/span&gt; 2 &lt;span class="nv"&gt;$low&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt; | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect upper layer (It's empty)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container inspect test_overlayfs &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{.GraphDriver.Data.UpperDir}}'&lt;/span&gt; | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;upper&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;tree &lt;span class="nv"&gt;$upper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt; | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run command withing the container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install &lt;/span&gt;nmap &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect (again) upper layer (now it's not empty)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container inspect test_overlayfs &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{.GraphDriver.Data.UpperDir}}'&lt;/span&gt; | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;upper&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;tree &lt;span class="nv"&gt;$upper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt; | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inspect docker process namespace
&lt;/h2&gt;

&lt;p&gt;Run docker container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; test_ps &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch process within container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;600 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;600 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;600 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;600 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;600 &amp;amp;
&lt;span class="nv"&gt;$ &lt;/span&gt;top
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See container tree process from container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ CONTAINER_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;docker container top test_ps | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'2p'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ps f &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_PID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List PID namespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lsns &lt;span class="nt"&gt;-t&lt;/span&gt; pid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See process using docker&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container top test_ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this tutorial we create our first container from scratch understanding what happen behind the scenes when we run a container. I hope this tutorial helps you to understand the technologies behind the linux containers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ivanmorenoj/how-containers-works"&gt;Source code&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>kubernetes</category>
      <category>containers</category>
    </item>
    <item>
      <title>How to deploy pihole and wireguard on kubernetes (DNS over HTTPS)</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Mon, 01 Mar 2021 13:51:43 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-deploy-pihole-and-wireguard-on-kubernetes-using-a-recursive-dns-4l9</link>
      <guid>https://dev.to/ivanmoreno/how-to-deploy-pihole-and-wireguard-on-kubernetes-using-a-recursive-dns-4l9</guid>
      <description>&lt;p&gt;In this tutorial we are going to deploy a DNS ad-blocker with pihole using a recursive DNS as upstream server accessible in LAN network and internet through wireguard vpn. We utilized &lt;a href="https://k3s.io" rel="noopener noreferrer"&gt;K3S&lt;/a&gt; as kubernetes provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial you need to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A computer running any linux distribution (in this tutorial I'm using debian buster)&lt;/li&gt;
&lt;li&gt;This computer needs to have at least 1 Gb of ram and 2 cores.&lt;/li&gt;
&lt;li&gt;This computer needs to have an static ip address (in my case 192.168.10.10, LAN: 192.168.10.1/24)&lt;/li&gt;
&lt;li&gt;Configure the firewall to accept inbound connections in the following ports:

&lt;ul&gt;
&lt;li&gt;53/tcp&lt;/li&gt;
&lt;li&gt;53/udp&lt;/li&gt;
&lt;li&gt;80/tcp&lt;/li&gt;
&lt;li&gt;443/tcp&lt;/li&gt;
&lt;li&gt;51820/udp&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;In order to connect from internet, you need to open the following ports in your ISP's Router:

&lt;ul&gt;
&lt;li&gt;80/tcp (Pihole Web Interface HTTP) &lt;/li&gt;
&lt;li&gt;443/tcp (Pihole Web Interface HTTPS) &lt;/li&gt;
&lt;li&gt;51820/tcp (Wireguard VPN) &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;In order to connect to pihole via web UI from internet you need to have a &lt;code&gt;FQDN&lt;/code&gt; that points to your Network (in this tutorial I'm using google domains, you can use &lt;a href="https://www.duckdns.org/" rel="noopener noreferrer"&gt;duckdns&lt;/a&gt; if you don't have a domain)&lt;/li&gt;

&lt;li&gt;A functional K3S cluster (See &lt;a href="https://rancher.com/docs/k3s/latest/en/installation/install-options/" rel="noopener noreferrer"&gt;Installation guide&lt;/a&gt;). This tutorial should work with K8S, but you need to deploy some extra features like Traefik Ingress, Klipper Service Load Balancer&lt;/li&gt;

&lt;li&gt;You need to have &lt;code&gt;kubectl&lt;/code&gt; to perform operations in the K3S cluster&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  System Architecture
&lt;/h2&gt;

&lt;p&gt;In the following image you can see the diagram that we want to implement. We can access to pihole in our local network (192.168.10.1/24) and access to admin interface through internet, finally we can access to cluster resources via VPN trough Wireguard or just route dns queries.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb8dm814gmgwujj5u45h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb8dm814gmgwujj5u45h.jpg" alt="diagram"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;All manifests are in this &lt;a href="https://github.com/ivanmorenoj/k3s-pihole-wireguard" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; feel free to clone and customize&lt;/p&gt;
&lt;h1&gt;
  
  
  Methodology
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Namespaces
&lt;/h2&gt;

&lt;p&gt;The first thing that we need to configure is the &lt;code&gt;namespace&lt;/code&gt; we need to create 2 namespaces: &lt;code&gt;pihole&lt;/code&gt; for pihole, unbound and wireguard. &lt;code&gt;cert-manager&lt;/code&gt; to deploy a cert manager in order to enable HTTPS on pihole UI interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/01-namespaces.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dynamic DNS
&lt;/h2&gt;

&lt;p&gt;If you don't have assigned an static ip address, you can point to your public ip provided by your ISP using a dynamic dns, in my case I'm using a google domains, so i can update the subdomain with curl. I created a &lt;code&gt;cronJob&lt;/code&gt; that updates every 5 min the public ip assigned by my ISP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/02-dynamic-dns-google.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create directories
&lt;/h2&gt;

&lt;p&gt;To store config files you need to create 2 directories in the master node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/lib/&lt;span class="o"&gt;{&lt;/span&gt;pihole,wireguard&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pihole
&lt;/h2&gt;

&lt;p&gt;Pihole (as you probably already know) is a dns add blocker. In order to configure Pihole and make accessible in our LAN network we need to configure a &lt;code&gt;LoadBalancer&lt;/code&gt; service in 53/tcp-udp that binds in the local host. The web UI will be accessible through Ingress controller (If you don't want that just use a &lt;code&gt;NodePort&lt;/code&gt; service in &lt;code&gt;pihole-ui-svc&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;This manifest comes with three different configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pihole with upstream servers&lt;/li&gt;
&lt;li&gt;Pihole with unbound&lt;/li&gt;
&lt;li&gt;Pihole with DNS over HTTP(S) with cloudflare DNS servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Common configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent volume type &lt;code&gt;hostPath&lt;/code&gt; (&lt;code&gt;/var/lib/pihole&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Persistent Volume claim&lt;/li&gt;
&lt;li&gt;Config Map (Timezone, admin email and upstream dns)&lt;/li&gt;
&lt;li&gt;Secret (Web Password)&lt;/li&gt;
&lt;li&gt;Pihole &lt;code&gt;Deployment&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Cluster IP Services (Pihole UI, Pihole DNS)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LoadBalancer&lt;/code&gt; Services (Pihole DNS bind to host)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need to configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time Zone (pihole-configmap)&lt;/li&gt;
&lt;li&gt;Admin email (pihole-configmap)&lt;/li&gt;
&lt;li&gt;Web Password (pihole-secret)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pihole with upstream servers
&lt;/h3&gt;

&lt;p&gt;This configuration forwards the dns queries to an upstream server like cloudflare dns &lt;code&gt;1.1.1.1&lt;/code&gt; and google dns &lt;code&gt;8.8.8.8&lt;/code&gt; with no encryption.&lt;/p&gt;

&lt;p&gt;To apply this configuration use the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/03-pihole-upstream-dns.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pihole with unbound
&lt;/h3&gt;

&lt;p&gt;Unbound is a validating, recursive, caching DNS resolver. In order to resolve a dns query unbound queries to the root domain (.com), then queries to subdomain (example.com) and keeps doing til it found the desire domain (pihole.example.com). Is very useful to avoid some type of tracking in the popular dns servers (like google). In this tutorial we utilize this image &lt;a href="https://hub.docker.com/r/mvance/unbound" rel="noopener noreferrer"&gt;mvance/unbound&lt;/a&gt; that comes pre-configured to works as recursive dns.&lt;/p&gt;

&lt;p&gt;To apply this configuration use the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/03-pihole-unbound.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Test Unbound installation&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfjmc1vplpcrbauwtriw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfjmc1vplpcrbauwtriw.png" alt="unbound-dig-example"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Pihole with DNS over HTTP(S) with cloudflare DNS servers
&lt;/h3&gt;

&lt;p&gt;This configuration forward DNS queries to cloudflare dns server over https, ie. all queries are being encrypted since they are using TLS to perform the connection with cloudflare. Your ISP does not know what DNS request you are making. &lt;/p&gt;

&lt;p&gt;To apply this configuration use the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/03-pihole-DoH-cloudflare.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test Pihole installation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7c9du4gvsx2ljw1dhxn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7c9du4gvsx2ljw1dhxn.png" alt="pihole-dig-test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  WireGuard
&lt;/h2&gt;

&lt;p&gt;WireGuard is a modern VPN server that works at kernel level. In this tutorial we utilize the vpn to access at LAN resources from internet or just to encrypt the dns queries to our pihole installation from internet.&lt;/p&gt;

&lt;p&gt;This manifest comes with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent volume type &lt;code&gt;hostPath&lt;/code&gt; (&lt;code&gt;/var/lib/wireguard&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Persistent Volume claim&lt;/li&gt;
&lt;li&gt;Config Map (Timezone, server url, number of peers, etc)&lt;/li&gt;
&lt;li&gt;Wireguard &lt;code&gt;StatefulSet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LoadBalancer&lt;/code&gt; Service (Wireguard listen port 51820/udp)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need to configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timezone (wireguard-configmap)&lt;/li&gt;
&lt;li&gt;Server URL (wireguard-configmap)&lt;/li&gt;
&lt;li&gt;Number of peers (wireguard-configmap)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/04-wireguard.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wireguard Client config
&lt;/h3&gt;

&lt;p&gt;You can see the logs of your wireguard pod to get the QR code for each peer as is showed in the following image&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqj9lwzaiz76bqw7uzc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqj9lwzaiz76bqw7uzc6.png" alt="wg-qr"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also copy the config files for each peer located at &lt;code&gt;/var/lib/wireguard/config/peer&amp;lt;N&amp;gt;/peer&amp;lt;N&amp;gt;.conf&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Extra (Ingress Configuration for Pihole UI)
&lt;/h1&gt;

&lt;p&gt;This steps describe how to make the Pihole Web User Interface available from internet &lt;code&gt;HTTP/HTTPS&lt;/code&gt; using &lt;code&gt;Traefik&lt;/code&gt; Ingress. If you don't want that, just use a &lt;code&gt;NodePort&lt;/code&gt; service in &lt;code&gt;pihole-ui-svc&lt;/code&gt;. &lt;/p&gt;
&lt;h2&gt;
  
  
  Deploy cert-manager
&lt;/h2&gt;

&lt;p&gt;We need to deploy a cert manager to serve TLS certificates for HTTPS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploy Cluster Issuer (Let's Encrypt)
&lt;/h2&gt;

&lt;p&gt;This manifest deploy a cluster issuer that points to Let's encrypt. You need to configure the email to get notifications.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/05-cluster-issuer-letsencrypt.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ingress
&lt;/h2&gt;

&lt;p&gt;This manifest comes with the domain of your pihole host. You need to configure the subdomain previously configured.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/06-ingress.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  How to use
&lt;/h1&gt;

&lt;p&gt;You can change your LAN &lt;code&gt;DNS&lt;/code&gt; servers to point to your pihole installation. If you're in a VPN by default you route all of your traffic trough wireguard including your dns queries. If you only want to route your dns queries through wireguard you should only route the following routes in &lt;code&gt;AllowedIPS&lt;/code&gt;: &lt;code&gt;10.0.0.0/8&lt;/code&gt;, &lt;code&gt;192.168.10.0/24&lt;/code&gt; (replace whit your local network CIDR).&lt;/p&gt;

&lt;p&gt;If you have been following this tutorial so far you will see the following resources on your kubernetes cluster&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhu3hb1h3fmtu1ar1n7em.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhu3hb1h3fmtu1ar1n7em.png" alt="full-installation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the Pihole admin User Interface accessible through internet via &lt;code&gt;FQDN&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjf4bjvaul4qg9xwnhie.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjf4bjvaul4qg9xwnhie.jpg" alt="pihole-ui"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>doh</category>
      <category>pihole</category>
      <category>wireguard</category>
    </item>
    <item>
      <title>How to connect to kubernetes internal network using WireGuard</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Fri, 13 Nov 2020 07:12:35 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-connect-with-kubernetes-internal-network-using-wireguard-48bh</link>
      <guid>https://dev.to/ivanmoreno/how-to-connect-with-kubernetes-internal-network-using-wireguard-48bh</guid>
      <description>&lt;p&gt;When you are testing your deployments in a kubernetes cluster on the cloud you have a few options to expose your services outside world, for example you can use a &lt;code&gt;NodePort&lt;/code&gt; service, but also you need to configure the firewall rules for each &lt;code&gt;NodePort&lt;/code&gt; service, the other type of service that you can use is &lt;code&gt;LoadBalancer&lt;/code&gt; however each of them is billed by cloud provider. To solve this problem you can use a vpn running within your k8s cluster, this vpn can be exposed outside the cluster with a &lt;code&gt;NodePort&lt;/code&gt; or &lt;code&gt;LoadBalancer&lt;/code&gt; service. As client you can access to you kubernetes internal network using service &lt;code&gt;FQDN&lt;/code&gt; in your local machine.&lt;/p&gt;

&lt;p&gt;In this tutorial we gonna setup a pod that run wireguard server, this wireguard will be configured with the kube-dns service and generate cliente credentials automatically the diagram will be like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmyl0ixaymavtbsnlkycm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmyl0ixaymavtbsnlkycm.png" alt="diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assuming that you are in a testing k8s cluster in the cloud with multiple namespaces and services. &lt;/p&gt;

&lt;p&gt;First we need to know the &lt;code&gt;kube-dns&lt;/code&gt; IP address with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system get svc | &lt;span class="nb"&gt;grep &lt;/span&gt;kube-dns | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt;
&lt;span class="c"&gt;# output example: 10.124.0.10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to isolate wireguard server from another apps, we need to create a wireguard namespace named &lt;code&gt;wireguard&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To store wireguard config files, we need a persistent volume, in my case i’m using a gke managed service that provides me a storage class, so i’m gonna create a persistent volume claim to that storage class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pv-claim-wireguard&lt;/span&gt; 
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;storageClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard"&lt;/span&gt;
  &lt;span class="na"&gt;accessModes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ReadWriteOnce&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing to configure is the environment variables of wireguard server, this will be do with a config map. The &lt;code&gt;kube-dns&lt;/code&gt; IP from steps earlier will be set in &lt;code&gt;PEERDNS&lt;/code&gt; field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConfigMap&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard-configmap&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;PUID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1000"&lt;/span&gt;
  &lt;span class="na"&gt;PGID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1000"&lt;/span&gt;
  &lt;span class="na"&gt;TZ&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;America/Mexico_City"&lt;/span&gt;
  &lt;span class="na"&gt;SERVERPORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;31820"&lt;/span&gt;
  &lt;span class="na"&gt;PEERS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;
  &lt;span class="na"&gt;PEERDNS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10.124.0.10"&lt;/span&gt;
  &lt;span class="na"&gt;ALLOWEDIPS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0/0,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;::/0"&lt;/span&gt;
  &lt;span class="na"&gt;INTERNAL_SUBNET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10.13.13.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create the wireguard server pod, this pod needs to be privileged with &lt;code&gt;NET_ADMIN&lt;/code&gt; and &lt;code&gt;SYS_MODULE&lt;/code&gt; capabilities and needs to mount &lt;code&gt;/lib/modules&lt;/code&gt; directory from the host. The image used is &lt;code&gt;ghcr.io/linuxserver/wireguard&lt;/code&gt; from &lt;a href="https://hub.docker.com/r/linuxserver/wireguard" rel="noopener noreferrer"&gt;linuxserver.io&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/linuxserver/wireguard&lt;/span&gt;
    &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configMapRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard-configmap&lt;/span&gt; 
    &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NET_ADMIN&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SYS_MODULE&lt;/span&gt;
      &lt;span class="na"&gt;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wg-config&lt;/span&gt;
        &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/config&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;host-volumes&lt;/span&gt;
        &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/lib/modules&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;51820&lt;/span&gt;
      &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UDP&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;64Mi"&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100m"&lt;/span&gt;
      &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;128Mi"&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;200m"&lt;/span&gt;
  &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wg-config&lt;/span&gt;
      &lt;span class="na"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;claimName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pv-claim-wireguard&lt;/span&gt; 
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;host-volumes&lt;/span&gt;
      &lt;span class="na"&gt;hostPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/lib/modules&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally to access to wireguard server, we need to create a service, this service could be a &lt;code&gt;NodePort&lt;/code&gt; or &lt;code&gt;LoadBalancer&lt;/code&gt;, in my case i used a &lt;code&gt;NodePort&lt;/code&gt; service on port &lt;code&gt;31820&lt;/code&gt;, take in mind that you probably need to configure a firewall rule to access at this service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;k8s-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard-service&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;51820&lt;/span&gt;
    &lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;31820&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UDP&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;51820&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wireguard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configurations are in a single file &lt;code&gt;wireguard-pod.yaml&lt;/code&gt; to execute just apply the file with &lt;code&gt;kubectl&lt;/code&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; wireguard-pod.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container generate a &lt;code&gt;QR&lt;/code&gt; code for each peer, these &lt;code&gt;QR&lt;/code&gt; appears in the logs of the pod, to see just type the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; wireguard logs wwireguard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will be like this&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9fvwbs1xy7kckcdro6eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9fvwbs1xy7kckcdro6eb.png" alt="qr-code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to connect to wireguard server download mobile app of install in your local machine. See &lt;a href="https://www.wireguard.com/install/" rel="noopener noreferrer"&gt;wireguard.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can scan the code with the mobile app or copy the config file in your computer at &lt;code&gt;~/peer1.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; wireguard &lt;span class="nb"&gt;exec &lt;/span&gt;wireguard &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; /config/peer1/peer1.conf &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/peer1.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can utilize the config file to activate the vpn. With &lt;code&gt;NetworManager&lt;/code&gt; you can import the config file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nmcli connection import &lt;span class="nb"&gt;type &lt;/span&gt;wireguard file ~/peer1.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And activate or deactivate the connection&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nmcli connection up peer1 
&lt;span class="nv"&gt;$ &lt;/span&gt;nmcli connection down peer1 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally to access a &lt;code&gt;ClusterIP&lt;/code&gt; service within k8s cluster just use the IP of &lt;code&gt;ClusterIP&lt;/code&gt; service or use the &lt;code&gt;FQDN&lt;/code&gt; of the service using the following rule&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;clusterip-service&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the output of &lt;code&gt;dig&lt;/code&gt; in a &lt;code&gt;FQDN&lt;/code&gt; inside a remote k8s cluster, note that the query is answered by &lt;code&gt;kube-dns&lt;/code&gt; IP inside the k8s cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl42uogs1fu9kqayumzxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl42uogs1fu9kqayumzxc.png" alt="dig-output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example to access a &lt;code&gt;ClusterIP&lt;/code&gt; service named &lt;code&gt;thingsboard-service&lt;/code&gt; in the namespace &lt;code&gt;thingsboard&lt;/code&gt; at &lt;code&gt;9090&lt;/code&gt; port from our local machine through wireguard vpn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://thingsboard-service.thingsboard.svc.cluster.local:9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the output in our local environment&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdvbqxrs1b7dm6w0ptjmz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdvbqxrs1b7dm6w0ptjmz.png" alt="web-app-test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This method is very useful for a managed kubernetes service in the cloud in a development environment because we can test our services without configure a nodeport for each service and his respectively firewall rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WARNING: Only use this method in a development environment, don't use in a production environment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ivanmorenoj/k8s-wireguard" rel="noopener noreferrer"&gt;Source Code&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
      <category>cloud</category>
      <category>wireguard</category>
    </item>
    <item>
      <title>How to bypass a firewall using a VPS on AWS</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Sun, 20 Sep 2020 07:00:30 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-bypass-firewall-at-work-or-school-1-2-4oh2</link>
      <guid>https://dev.to/ivanmoreno/how-to-bypass-firewall-at-work-or-school-1-2-4oh2</guid>
      <description>&lt;p&gt;When you browse at school or work you probably have experienced some problems browsing in certain websites or using certain applications. Is a common practice to block some kind of pages on internet at work or school environment also they block another kind of traffic such as torrents, adult-content or they just permit web traffic, you school or work don't want you to browse sites they haven't approved.&lt;/p&gt;

&lt;h1&gt;
  
  
  Types of firewall blocking
&lt;/h1&gt;

&lt;p&gt;There are certain levels of firewall blocking, the most simple is based on blocking certain kind of web-pages. The other type of firewall blocking is based on protocols, they just allow certain kind of traffic such as web traffic, ssh, dns, etc. Almost every school or work place have both kind of firewall blocking, but there is more sophisticated blocking levels, in this article we only focus on this type of firewall blocking.&lt;/p&gt;

&lt;h1&gt;
  
  
  Who wants to bypass a firewall?
&lt;/h1&gt;

&lt;p&gt;There are some many types of users who wants to bypass a firewall for different reasons, this reasons could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wants to browse in certain kind of web pages&lt;/li&gt;
&lt;li&gt;Wants to use specific application that are blocked such a torrent&lt;/li&gt;
&lt;li&gt;Needs to access a school or work environment behind a firewall&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are different methods to bypass a firewall according to their usage. For the first kind of user who only wants to browse in blocked websites, the method could be a VPN or proxy. For the second kind of user who wants to use specific non web application, the method could be a VPN. The last kind of user wants to expose some service running behind firewall such a ssh server running at school or workplace, the method for this user could be ssh port forwarding or VPN with port forwarding on server-side.&lt;/p&gt;

&lt;h1&gt;
  
  
  Disclaimer
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;This tutorial was made for informational and educational purposes only. I cannot be held responsible for any misuse of the given information. If you plan to use the information for illegal purposes, please leave this tutorial now.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Before begin
&lt;/h1&gt;

&lt;p&gt;In this tutorial we are gonna setup a VPN server, Proxy server and SSH server to bypass a firewall, normally some services are't blocked by the firewall such http, https, ssh and DNS it means that we can setup any service on these ports for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Squid proxy on port 80/tcp&lt;/li&gt;
&lt;li&gt;SSH server on port 22/tcp&lt;/li&gt;
&lt;li&gt;OpenVPN on port 443/tcp&lt;/li&gt;
&lt;li&gt;Wireguard VPN on port 53/udp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these services have advantages and disadvantages and serves a specific purpose for example you can use ssh tunnel as sock proxy, forward ports through ssh tunnel using ssh port forwarding this is useful but in some application and mobile devices this method is not enough. Using a proxy y very useful if you only want to browse in blocked web pages. A vpn is the best solution to navigate without restrictions, it works on desktop and mobile devices, you can forward traffic from internet to client or make available a private subnet connecting client to client through VPS server using a gateway device such raspberry pi. In this tutorial I setup 2 vpns, wireguard and openvpn, in my personal opinion wireguard is better than openvpn but wireguard does't work with tcp protocol, that's why i set wireguard at 53/udp and openvpn at 443/tcp one advantage of openvpn is his protocol that utilizes SSL/TLS for key exchange so in a packet analysis will appears like https traffic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configure VPS on AWS
&lt;/h1&gt;

&lt;p&gt;For all services we need a virtual private server (VPS), this vps could be setup on any public cloud provider, in my case i chose aws because they offer one year of free trial on aws EC2.&lt;/p&gt;

&lt;p&gt;The first step is create an account in aws, create a VPS, configure a key pair and security group. I choose ubuntu 20.04 with the following configuration. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbyyh62byl7n7ts4k56wn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbyyh62byl7n7ts4k56wn.png" alt="aws-ec2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to avoid a change os ip when the VPS restart i recommend to associate a static ip address, this can be set in &lt;em&gt;elastic ip&lt;/em&gt; option as shown in the following image&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6eozhvhb411be9ukrf7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6eozhvhb411be9ukrf7y.png" alt="elastic-ip"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Access to VPS
&lt;/h2&gt;

&lt;p&gt;We need to download the key pair created steps earlier and move to &lt;code&gt;~/.ssh&lt;/code&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; ~/Downloads/aws.pem ~/.ssh/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change file permissions to be only readable for user owner&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;400 ~/.ssh/aws.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access to remote VPS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/aws.pem ubuntu@&amp;lt;public_ip_address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install needed packages
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;wireguard squid fail2ban qrencode apache2-utils &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure fail2ban
&lt;/h2&gt;

&lt;p&gt;fail2ban is a tool that helps to prevent automated brute force attacks in services exposed to internet.&lt;/p&gt;

&lt;p&gt;Add sshd jail in &lt;code&gt;/etc/fail2ban/jail.d/sshd-jail.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[sshd]
enabled   = true
maxretry  = 3
findtime  = 1d
bantime   = 4w
ignoreip  = 127.0.0.1/8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload fail2ban service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl restart fail2ban
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check sshd jail&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;fail2ban-client status sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure SSH server
&lt;/h2&gt;

&lt;p&gt;In order to setup a ssh port forwarding we need to configure some options in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; to allow TCP Forwarding and Gateway Ports&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AllowTcpForwarding yes
GatewayPorts yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload the ssh server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl restart sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can setup port forwarding through ssh tunnels, check &lt;a href="https://link.medium.com/NBkzEmAf29" rel="noopener noreferrer"&gt;this&lt;/a&gt; tutorial to create a systemd service with ssh tunnel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure squid proxy on 80/tcp
&lt;/h2&gt;

&lt;p&gt;Squid is a http proxy, it can be configured on port 80 to bypass firewall.&lt;br&gt;
Configure squid proxy to listen in port 80 and basic user authentication.&lt;/p&gt;

&lt;p&gt;Create user and password&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;htpasswd &lt;span class="nt"&gt;-c&lt;/span&gt; /etc/squid/passwd client1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate config file, first create a backup of original file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; /etc/squid/squid.conf /etc/squid/squid.conf.bk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate squid config file in &lt;code&gt;/etc/squid/squid.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; /etc/squid/squid.conf
acl localnet src 0.0.0.1-0.255.255.255  # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8             # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10          # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16         # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12          # RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16         # RFC 1918 local private network (LAN)
acl localnet src fc00::/7               # RFC 4193 local private network range
acl localnet src fe80::/10              # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT

auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic children 5
auth_param basic realm Squid Basic Authentication
auth_param basic credentialsttl 2 hours
acl auth_users proxy_auth REQUIRED
http_access allow auth_users

http_access deny !Safe_ports

http_access deny CONNECT !SSL_ports

http_access allow localhost manager
http_access deny manager

include /etc/squid/conf.d/*

http_access allow localhost

http_access deny all

http_port 80

coredump_dir /var/spool/squid

refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|&lt;/span&gt;&lt;span class="se"&gt;\?&lt;/span&gt;&lt;span class="sh"&gt;) 0     0%      0
refresh_pattern &lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sh"&gt;(Packages|Sources)(|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sh"&gt;bz2|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sh"&gt;gz|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sh"&gt;xz)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="sh"&gt;0 0% 0 refresh-ims
refresh_pattern &lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sh"&gt;Release(|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sh"&gt;gpg)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="sh"&gt;0 0% 0 refresh-ims
refresh_pattern &lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sh"&gt;InRelease&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="sh"&gt;0 0% 0 refresh-ims
refresh_pattern &lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sh"&gt;(Translation-.*)(|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sh"&gt;bz2|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sh"&gt;gz|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sh"&gt;xz)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="sh"&gt;0 0% 0 refresh-ims
refresh_pattern .               0       20%     4320
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart squid service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl restart squid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can configure a proxy in your browser, system or phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Wireguard at 53/udp
&lt;/h2&gt;

&lt;p&gt;Wireguard is modern VPN protocol that works on kernel-side, unfortunately only works on &lt;strong&gt;UDP&lt;/strong&gt; ports and most of firewalls blocks outgoing udp connections except in some services such a DNS on 53/UDP so we'll configure wireguard to listen in 53/UDP.&lt;/p&gt;

&lt;p&gt;First of all, we need to enable ip forwarding&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sysctl &lt;span class="nt"&gt;-w&lt;/span&gt; net.ipv4.ip_forward&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make changes permanent uncomment this line &lt;code&gt;net.ipv4.ip_forward=1&lt;/code&gt; in &lt;code&gt;/etc/syctl.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'/net.ipv4.ip_forward/s/^#//g'&lt;/span&gt; /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of systemd based distros uses &lt;strong&gt;&lt;em&gt;systemd-resolve&lt;/em&gt;&lt;/strong&gt; to resolve dns queries, this is a problem if we want to setup wireguard to listen on 53/udp, so we need to disable systemd-resolve, first of all check what process is listen on port 53/UDP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ss &lt;span class="nt"&gt;-ulpn4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see in the following image, the process who listen on port 53/UDP is &lt;em&gt;systemd-resolve&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm3oxaz9s56i0rkvd6o0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm3oxaz9s56i0rkvd6o0g.png" alt="systemd-resolve"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Disable systemd-resolve&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl disable &lt;span class="nt"&gt;--now&lt;/span&gt; systemd-resolved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set static dns server adding this lines on &lt;code&gt;/etc/resolv.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nameserver 1.1.1.1
nameserver 1.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can check again who is using port 53/udp with this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ss &lt;span class="nt"&gt;-ulpn4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A this point we need to generate a config file for wireguard server.&lt;br&gt;
Before create a config file check what is you default interface in my case is eth0, modify wireguard config file according to your interface name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-4&lt;/span&gt; route show to default | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create wireguard config file at &lt;code&gt;/etc/wireguard/wgserver.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Interface]
Address = 10.20.0.1/24
ListenPort = 53
PrivateKey = &amp;lt;your_private_key&amp;gt;
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
SaveConfig = true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate wireguard private key and put in &lt;code&gt;/etc/wireguard/wgserver.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"s/&amp;lt;your_private_key&amp;gt;/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;wg genkey&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt; /etc/wireguard/wgserver.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable wireguard server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; wg-quick@wgserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate client template at &lt;code&gt;~/wgclients/template.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Interface]
PrivateKey = &amp;lt;private_key&amp;gt;
Address = 10.20.0.xxx/32

[Peer]
PublicKey = &amp;lt;server_public_key&amp;gt;
Endpoint = &amp;lt;public_ip_address&amp;gt;:53
AllowedIPs = 0.0.0.0/0, ::/0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get server public key, replace this in &lt;code&gt;&amp;lt;server_public_key&amp;gt;&lt;/code&gt; in &lt;code&gt;~/wgclients/template.conf&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;wg show wgserver | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/public key:/{print $3}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set server public ip address in &lt;code&gt;~/wgclients/template.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"s/&amp;lt;public_ip_address&amp;gt;/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; ifconfig.me/ip&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt; ~/wgclients/template.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate client and copy template&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/wgcliets/client1
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; ~/wgclients/template.conf ~/wgcliets/client1/client1.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate client keys&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/wgclients/client1
&lt;span class="nv"&gt;$ &lt;/span&gt;wg genkey | &lt;span class="nb"&gt;tee &lt;/span&gt;private-key | wg pubkey &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; public-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy private key and paste in &lt;code&gt;~/wgclients/client1.conf&lt;/code&gt; file and set ip address. Add client public key in &lt;code&gt;/etc/wireguard/wgserver.conf&lt;/code&gt; and tunnel ip address&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Peer]
PublicKey = &amp;lt;client_public_key&amp;gt;
AllowedIPs = 10.20.0.10/32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload config on-the-fly&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;su &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"wg addconf wgserver &amp;lt;(wg-quick strip wgserver)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check wireguard connection, download wireguard android app in PlayStore. Generate QR code from client config file and import in wireguard app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;qrencode &lt;span class="nt"&gt;-t&lt;/span&gt; ansiutf8 &amp;lt; ~/wgclients/client1/client1.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can check connection typing &lt;code&gt;ifconfig.me&lt;/code&gt; at mobile web browser it will appears the server public ip address&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure OpenVPN at 443/tcp
&lt;/h2&gt;

&lt;p&gt;OpenvPN is a vpn that uses a custom security protocol that utilizes SSL/TLS for key exchange so it could be set in HTTPS port since every web site uses SSL/TSL the firewall cannot block that port.&lt;/p&gt;

&lt;p&gt;Install OpenVPN with automated script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/Nyr/openvpn-install.git
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;openvpn-install
&lt;span class="nv"&gt;$ &lt;/span&gt;bash openvpn-install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure using the following parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use IPV4 address in eth0 in my case 172.31.14.144&lt;/li&gt;
&lt;li&gt;Put public ipv4 address&lt;/li&gt;
&lt;li&gt;Protocol: TCP&lt;/li&gt;
&lt;li&gt;Port: 443&lt;/li&gt;
&lt;li&gt;DNS: 1.1.1.1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Configurations is showed in the following image&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvqlhyth12l7rew3cdqd2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvqlhyth12l7rew3cdqd2.png" alt="openvpn"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The client config file will be placed on &lt;code&gt;/root&lt;/code&gt; directory, copy to home&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/ovpnclients
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; /root/client1.ovpn /home/ubuntu/ovpnclients/
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;ubuntu:ubuntu ~/ovpnclients/client1.ovpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download config file to your pc and transfer to android app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/aws.pem ubuntu@&amp;lt;public_ip_address&amp;gt;:~/ovpnclients/client1.ovpn ~/ovpnclients
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import file in android app and connect, type &lt;code&gt;ifconfig.me&lt;/code&gt; it will appears the server public ip address.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;These methods will work in almost all scenarios, please use them at your own risk because these methods can open a security breach in your work environment.&lt;/p&gt;

</description>
      <category>vpn</category>
      <category>linux</category>
      <category>cloud</category>
      <category>openvpn</category>
    </item>
    <item>
      <title>How to install and configure your own VPN server in GCP with Wireguard</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Sun, 16 Aug 2020 01:44:59 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-install-and-configure-you-own-vpn-server-in-gcp-with-wireguard-2af0</link>
      <guid>https://dev.to/ivanmoreno/how-to-install-and-configure-you-own-vpn-server-in-gcp-with-wireguard-2af0</guid>
      <description>&lt;p&gt;Security is one of the most important things now days specifically in enterprise environments, a vpn helps to encrypt traffic from client to internet. Wireguard is a vpn protocol than works on the kernel side and acts like a network interface, is one of the most modern vpn protocols it’s based in public and private key exchange just like ssh does. A vpn can connect different host with encrypted connection throught internet, this topology can connect a simple client in an android app or even connect different hosts across datacenters, for example to connect workers in Kubernetes/swarm cluster in different datacenters regions with encrypted connection without open any public API on internet, wireguard also can be used to connect different home based host across internet only opening one UDP port and use the vpn server as encrypted bridge between clients.&lt;br&gt;
In this tutorial we focus on implementation of vpn server on Google Cloud Platform (GCP) with wireguard, this setup will use a centos 8 on the server-side, and the configuration of one client in android device.&lt;/p&gt;
&lt;h2&gt;
  
  
  Server-side setup
&lt;/h2&gt;

&lt;p&gt;In the server side we will use CentOS 8 in GCP, the steps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a virtual instance&lt;/li&gt;
&lt;li&gt;Setup ssh keys&lt;/li&gt;
&lt;li&gt;Install Wireguard&lt;/li&gt;
&lt;li&gt;Configure Wireguard Server&lt;/li&gt;
&lt;li&gt;Configure clients&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Create virtual host in GCP &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this step we need to have an account in Google Cloud Platform and create a vm instance in compute engine. In this step you need to select the vm resource of you preference, in my case I choose a general purpose virtual machine with E2 series processor, I select the e2-small configuration with 2 vCPU and 2GB of ram, finally I choose centos 8 with 20 GB of ssd storage, the configuration is showed in next image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NTFJJDVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/8xg2toc9jjxkto2p288r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NTFJJDVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/8xg2toc9jjxkto2p288r.png" alt="gcp-vm" width="700" height="615"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup ssh keys &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In order to access to our virtual machine, we need to create a ssh key, the ssh key are create with this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/[KEY_FILENAME] &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;USERNAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, restrict the access of the key&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;400 ~/.ssh/[KEY_FILENAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get public ssh key and copy&lt;br&gt;
Copy directly from command line output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/[KEY_FILENAME].pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy with xclip from command line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/[KEY_FILENAME].pub | xclip &lt;span class="nt"&gt;-selection&lt;/span&gt; c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the public key in GCP. Go to Compute Engine -&amp;gt; Metadata -&amp;gt; SSH keys -&amp;gt; Edit -&amp;gt; Add item, then paste generated public ssh key&lt;br&gt;
Then paste in GCP and test ssh connection&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/[KEY_FILENAME] &lt;span class="o"&gt;[&lt;/span&gt;USER]@[PUBLIC_IP_ADDRESS]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Wireguard &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before install wireguard we need to update the system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we need to install some repositories&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;elrepo-release epel-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, install wireguard kmod and wireguard tools&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;kmod-wireguard wireguard-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure Wireguard Server &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before creating the wireguard config file is necessary to generate public and private key&lt;br&gt;
First change to root user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to &lt;code&gt;/etc/wireguard&lt;/code&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/wireguard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Limit default file permission of root user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;umask &lt;/span&gt;077
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate public and private key&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wg genkey | &lt;span class="nb"&gt;tee &lt;/span&gt;private-key | wg pubkey &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; public-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a wireguard config file in &lt;code&gt;/etc/wireguard/wgserver.conf&lt;/code&gt; and add the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Interface]
Address = 10.50.0.1/24
SaveConfig = true
PostUp = firewall-cmd --zone=public --add-port 50555/udp &amp;amp;&amp;amp; firewall-cmd --zone=public --add-masquerade &amp;amp;&amp;amp; firewall-cmd --zone=trusted --add-interface=wgserver &amp;amp;&amp;amp; firewall-cmd --zone=trusted --add-masquerade
PostDown = firewall-cmd --zone=public --remove-port 50555/udp &amp;amp;&amp;amp; firewall-cmd --zone=public --remove-masquerade &amp;amp;&amp;amp; firewall-cmd --zone=trusted --remove-interface=wgserver &amp;amp;&amp;amp; firewall-cmd --zone=trusted --remove-masquerade
ListenPort = 50555
PrivateKey = &amp;lt;private key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Config explained&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Address: the address of subnet in wireguard interface, it must be a private ip address class a, b or c&lt;/li&gt;
&lt;li&gt;SaveConfig: Update the config file when it added more users&lt;/li&gt;
&lt;li&gt;PostUp: This setting is executed when the interface initializes, in this case configure the firewall&lt;/li&gt;
&lt;li&gt;PostDown: This setting is executed when the interfaces shutdown, in this case remove firewall configuration&lt;/li&gt;
&lt;li&gt;ListenPort: The port where wireguard is listen (wireguard only listen udp ports)&lt;/li&gt;
&lt;li&gt;PrivateKey: Wireguard private key, this key was generated one step above in &lt;code&gt;/etc/wireguard/private-key&lt;/code&gt; copy and paste in &lt;code&gt;/etc/wireguard/wgserver.conf&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add firewall rules in GCP
&lt;/h3&gt;

&lt;p&gt;Go to VPC network -&amp;gt; Firewall -&amp;gt; Create new firewall rule&lt;br&gt;
To grant access to wireguard server add in source IP ranges 0.0.0.0/0, in protocols and ports add udp port on 50555 (ListenPort) then create the rule&lt;/p&gt;

&lt;p&gt;Enable wireguard server at boot with systemd&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; wg-quick@wgserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the status&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status wg-quick@wgserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will be like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gNqa0NtZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/jcmwx2b82d8ickcctksm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gNqa0NtZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/jcmwx2b82d8ickcctksm.png" alt="wg-status" width="700" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure clients &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To create peers, we need to create a folder wgclients and one template for all clients&lt;br&gt;
The &lt;code&gt;~/wgclients/template.conf&lt;/code&gt; file will be like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Interface]
PrivateKey = &amp;lt;client_private_key&amp;gt;
Address = 10.50.0.xxx/32
[Peer]
PublicKey = &amp;lt;server_public_key&amp;gt;
Endpoint = &amp;lt;server_public_ip_address&amp;gt;:&amp;lt;server_listen_port&amp;gt;
# to route all traffic through wireguard server 
# AllowedIPs = 0.0.0.0/0, ::/0
# to route only wireguard server subnet
AllowedIPs = 10.50.0.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a directory for each client, generate private and public key, copy template and replace client private key and address&lt;br&gt;
Create client directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/wgclients/client1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy template&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; ~/wgclients/template.conf ~/wgclients/client1/client1.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate client keys&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wg genkey | &lt;span class="nb"&gt;tee &lt;/span&gt;private-key | wg pubkey &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; public-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy client private key and paste in client config file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;private-key | xclip &lt;span class="nt"&gt;-selection&lt;/span&gt; c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;~/wgclients/client1/client1.conf&lt;/code&gt; and copy and paste client private key, the file will be like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Interface]
PrivateKey = QWERTfvCAJ5WgIqpCxOz9e7yYIzxOmB/PE1GBGNGJ29=
Address = 10.50.0.100/32
[Peer]
PublicKey = QWERTYvCAJ5WgIqpCxOz9e7yYIzxOmB/QWERTYNGJ20=
Endpoint = 32.54.69.87:50555
AllowedIPs = 10.50.0.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add client public key to &lt;code&gt;/etc/wireguard/wgserver.conf&lt;/code&gt; after Interface config add the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Peer]
PublicKey = QWERTYvCAJ5WgIqpCxOz9e7yYIzxOmB/QWERTYNGJ20=
# if client have static ip address put here, else omit the field
# Endpoint = 32.54.69.87:50555
AllowedIPs = 0.0.0.0/0, ::/0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then reload config file in server-side&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"wg addconf wgserver &amp;lt;(wg-quick strip wgserver)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check wireguard config status, will appers the new client&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;wg show wgserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then test connection, in this case with an android app. First download wireguard android app on google play store, generate QR from client config file and load from app&lt;/p&gt;

&lt;p&gt;Generate QR code from terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qrencode &lt;span class="nt"&gt;-t&lt;/span&gt; ansiutf8 &amp;lt; ~/wgclients/testclient/testclient.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example of QR code generated from command line&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sq6CWhRX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/2e620bfoz4jlj9mtqf1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sq6CWhRX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/2e620bfoz4jlj9mtqf1n.png" alt="wg-qr" width="497" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything works fine, type &lt;code&gt;ifconfig.me&lt;/code&gt; in android browser, it will appear the wireguard server address, from command line will appear the latest handshake and transfer data summary.&lt;/p&gt;

&lt;p&gt;Check connection in the server-side&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;wg show wgserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j2aTUxWQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/pdlqlap92rv4c34zmbn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j2aTUxWQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/pdlqlap92rv4c34zmbn4.png" alt="wg-show" width="469" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can add more android clients with the same method, for desktop clients I highly recommend to add &lt;code&gt;PersistentKeepalive&lt;/code&gt; option in server and client side, in the desktop you can use &lt;code&gt;NetworkManager&lt;/code&gt; to import a connection or use &lt;code&gt;systemd&lt;/code&gt; based service, also you can implement client config in OpenWrt router.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>wireguard</category>
      <category>vpnserver</category>
      <category>centos</category>
    </item>
    <item>
      <title>How to encrypt an existing archlinux LVM installation [LVM on LUKS]</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Sat, 15 Aug 2020 03:05:36 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-encrypt-an-existing-archlinux-lvm-installation-lvm-on-luks-1800</link>
      <guid>https://dev.to/ivanmoreno/how-to-encrypt-an-existing-archlinux-lvm-installation-lvm-on-luks-1800</guid>
      <description>&lt;p&gt;Many users need to secure their laptop, workstation or regular PC, this users want to protect their information. In Linux exist many cryptographic techniques to protect a hard disk, directory and partition, one of this techniques is Linux Unified Key Setup (LUKS) which uses the kernel device mapper subsystem via the dm-crypt module which make the encrypted device transparent to the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;p&gt;This tutorial only encrypt an existing LVM installation, the EFI and boot partitions are in a non-encrypted partition. In order to encrypt an existing LVM installation we need to have root permissions and an external temporally drive to allocate the entire volume group.&lt;br&gt;
In this tutorial the system drive is called &lt;code&gt;rootDrive&lt;/code&gt; and temporally drive is called &lt;code&gt;tmpDrive&lt;/code&gt;, the LVM root partition (partition to encrypt) is called &lt;code&gt;rootDriveXY&lt;/code&gt;, the temporally partition is called &lt;code&gt;tmpDriveXY&lt;/code&gt; both are formatted as Linux LVM.&lt;br&gt;
The entire system are installed in a single volume group, in this tutorial is called &lt;strong&gt;“vg-sys”&lt;/strong&gt;.&lt;br&gt;
You can realize the entire process without umount any partition because of flexibility of LVM, &lt;strong&gt;&lt;em&gt;in summary this process can be do on-the-fly&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Warning
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Only realize the process if you know what are you doing a bad execution can result in a system damage and data-loss. I recommend to realize a backup before starting this tutorial.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The specific case
&lt;/h2&gt;

&lt;p&gt;I have an existing archlinux installation on LVM volumes, the entire system is in a single volume group &lt;strong&gt;“arch”&lt;/strong&gt;, I have 5 logical volumes (swap, root, var, home and data) in a single physical volume, the entire disk have 3 partitions EFI (/dev/sdb1), boot (/dev/sdb2) and LVM (/dev/sdb3). In order to encrypt an existing LVM installation (/dev/sdb3) I have an empty temporally hard drive (/dev/sda1) with the minimum size of volume group allocated size, in my case the allocated size is 208 GiB (arch volume group), the temporally drive have 465 GiB (/dev/sda1), the temporally drive is formatted as Linux LVM, this setup is showing in the next image&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fttjdbkn671fep98ug1lv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fttjdbkn671fep98ug1lv.png" alt="specific-case"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;The first step is to create a physical volume in temporally drive, extend the &lt;strong&gt;“vg-sys”&lt;/strong&gt; volume group to temporally drive and move volume group to temporally drive.&lt;/p&gt;

&lt;p&gt;Create physical volume&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ pvcreate /dev/tmpDriveXY


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Extend "vg-sys" to temporally drive&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ vgextend vg-sys /dev/tmpDriveXY


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Move volume group to temporally drive&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ pvmove /dev/rootDriveXY /dev/tmpDriveXY


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the volume group is moved, reduce the &lt;code&gt;rootDriveXY&lt;/code&gt; from volume group “vg-sys” and remove the physical drive to be encrypted &lt;code&gt;/dev/rootDriveXY&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Remove physical drive from volume group&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ vgreduce vg-sys /dev/rootDriveXY


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Remove physical drive&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ pvremove /dev/rootDriveXY


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Change the partition type of root drive, on GPT the code is &lt;code&gt;8309&lt;/code&gt; for &lt;code&gt;Linux LUKS&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ gdisk /dev/rootDrive


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Change type with t, choose partition number&lt;br&gt;
Set type &lt;strong&gt;8309&lt;/strong&gt; for &lt;strong&gt;Linux LUKS&lt;/strong&gt;&lt;br&gt;
See changes whit &lt;strong&gt;p&lt;/strong&gt; and write with &lt;strong&gt;w&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ gdisk -l /dev/rootDrive  


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Wipe the partition to prevent cryptographic attacks or unwanted file recovery&lt;/p&gt;

&lt;p&gt;Create a temporary encrypted container&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ cryptsetup open --type plain -d /dev/urandom /dev/rootDeviceXY to_be_wiped


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Verify&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ lsblk


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Wipe with zeros, wait til &lt;strong&gt;"No space left on device"&lt;/strong&gt; be patient, this step takes a long time&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ dd if=/dev/zero of=/dev/mapper/to_be_wiped bs=1M status=progress


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Close wiped device&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ cryptsetup close to_be_wiped


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A this point probably you want to check performance of encrypt algorithms, use the next command to run a benchmark&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ cryptsetup benchmark


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fklp9q8kpmn3252l0s2gb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fklp9q8kpmn3252l0s2gb.png" alt="benchmark"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I choose an &lt;code&gt;aes-xts-plain64&lt;/code&gt; cipher with a key size of &lt;code&gt;256&lt;/code&gt; and &lt;code&gt;sha256&lt;/code&gt; hash. To encrypt the &lt;code&gt;rootDriveXY&lt;/code&gt; use the next command&lt;/p&gt;

&lt;p&gt;Encrypt device and set passphrase&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ cryptsetup -v --type luks --cipher aes-xts-plain64 --key-size 256 --hash sha256 --iter-time 2000 --use-urandom --verify-passphrase luksFormat /dev/rootDriveXY


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open encrypted device with passphrase, create a LVM physical volume, extend the &lt;strong&gt;“vg-sys”&lt;/strong&gt; volume to encrypted physical volume and move the temporally drive to encrypted&lt;/p&gt;

&lt;p&gt;Open encrypted volume&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ cryptsetup open /dev/rootDriveXY cryptarch


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create a physical LVM device&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ pvcreate /dev/mapper/cryptarch


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Extend the "vg-sys" group&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ vgextend vg-sys /dev/mapper/cryptarch


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Move volume group to encrypted drive&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ pvmove /dev/tmpDriveXY /dev/mapper/cryptarch


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now remove the temporally drive from LVM&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ vgreduce vg-sys /dev/tmpDriveXY


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Remove physical volume from temporally drive&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ pvremove /dev/tmpDriveXY 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configure &lt;em&gt;mkinitcpio&lt;/em&gt;, first edit &lt;code&gt;/etc/mkinitcpio.conf&lt;/code&gt; file and change hooks like this&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 filesystems fsck)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then recreate the &lt;em&gt;initramfs&lt;/em&gt; image for &lt;code&gt;linux-lts&lt;/code&gt; kernel&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ mkinitcpio -P linux-lts


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configuring the boot loader to unlock the encrypted root partition at boot, the following kernel parameter needs to be set by the boot loader, this can be set in &lt;code&gt;/etc/default/grub&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Get UUID of encrypted drive, in this case &lt;code&gt;/dev/rootDriveXY&lt;/code&gt; &lt;strong&gt;NOT&lt;/strong&gt; &lt;code&gt;/dev/mapper/cryptarch&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ blkid


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add this line in &lt;code&gt;GRUB_CMDLINE_LINUX&lt;/code&gt; option, in &lt;code&gt;/etc/default/grub&lt;/code&gt; file &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cryptdevice=UUID=rootDriveXY-UUID:cryptarch root=/dev/vg-sys/root


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Uncoment &lt;code&gt;GRUB_ENABLE_CRYPTODISK="y"&lt;/code&gt;&lt;br&gt;
Regenerate &lt;code&gt;/boot/grub/grub.cfg&lt;/code&gt; file&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ grub-mkconfig -o /boot/grub/grub.cfg


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If everything goes fine reboot the system and in boot time the system should ask a password to open the encrypted &lt;code&gt;rootDriveXY&lt;/code&gt; as shown in the next image&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhtt4g39yk56j6rsta3se.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhtt4g39yk56j6rsta3se.jpeg" alt="result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally I recommend to wipe the temporally drive to prevent unwanted data recovery.&lt;/p&gt;

</description>
      <category>archlinux</category>
      <category>luks</category>
      <category>lvm</category>
      <category>linux</category>
    </item>
    <item>
      <title>How to setup WiFi hotspot in raspberry pi and connect with ESP8266</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Fri, 14 Aug 2020 20:39:13 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-setup-wifi-hotspot-in-raspberry-pi-and-connect-with-esp8266-cg9</link>
      <guid>https://dev.to/ivanmoreno/how-to-setup-wifi-hotspot-in-raspberry-pi-and-connect-with-esp8266-cg9</guid>
      <description>&lt;h1&gt;
  
  
  Basic connection between arduino and raspberry pi through WiFi
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9shMYLL9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/4m456otm0n6akk34on1k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9shMYLL9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/4m456otm0n6akk34on1k.jpg" alt="test-hw" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hardware is
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Esp8266 with arduino sdk&lt;/li&gt;
&lt;li&gt;Raspberry pi 3b+&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  System requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;arduino-cli&lt;/li&gt;
&lt;li&gt;picocom&lt;/li&gt;
&lt;li&gt;python3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurations for Raspberry Pi
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install raspbian&lt;/li&gt;
&lt;li&gt;Enable ssh server&lt;/li&gt;
&lt;li&gt;Upgrade system&lt;/li&gt;
&lt;li&gt;Configure keys for ssh server&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md"&gt;Configure the raspberry pi as hotspot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install python3 and set as default python interpreter &lt;/li&gt;
&lt;li&gt;Copy server code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurations for ESP8266
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install esp8266 for arduino&lt;/li&gt;
&lt;li&gt;Copy the code and upload to esp8266 board &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Raspberry Pi Setup
&lt;/h1&gt;

&lt;p&gt;Download raspbian buster lite from official repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-LO&lt;/span&gt; http://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2020-02-14/2020-02-13-raspbian-buster-lite.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write to sd card&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;unzip &lt;span class="nt"&gt;-p&lt;/span&gt; 2020-02-13-raspbian-buster-lite.zip | &lt;span class="nb"&gt;sudo dd &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0 &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect the raspberry pi via Ethernet and HDMI, startup the system and access with &lt;code&gt;user=pi&lt;/code&gt; and &lt;code&gt;password=raspberry&lt;/code&gt;. Enable ssh service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check what is the ip address and logout from the system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip addr show eth0 &lt;span class="c"&gt;# copy ip address&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect via ssh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh pi@&lt;span class="o"&gt;{&lt;/span&gt;ip_address&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add user with the same privileges and groups to pi user, generate password and delete the pi user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;--groups&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;groups &lt;/span&gt;pi | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 4- &lt;span class="nt"&gt;--output-delimiter&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; new-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create password to &lt;code&gt;new-user&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;passwd new-user 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;new-user&lt;/code&gt; to sudoers file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"new-user ALL=(ALL) NOPASSWD: ALL"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/sudoers.d/010_new-user-nopasswd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Login to new user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;su new-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if sudo works&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check groups&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;groups &lt;/span&gt;new-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything works, logout and access to new-user with ssh, first logout&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate keys to &lt;code&gt;new-user&lt;/code&gt; and copy to raspberry pi&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh-keygen &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/rpi-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy public key to raspberry pi&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh-copy-id &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/rpi-key.pub new-user@&lt;span class="o"&gt;{&lt;/span&gt;raspberry-pi-ip&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now access to &lt;code&gt;new-user&lt;/code&gt; on raspberry pi&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh new-user@&lt;span class="o"&gt;{&lt;/span&gt;raspberry-pi-ip&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove &lt;code&gt;pi&lt;/code&gt; user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;userdel &lt;span class="nt"&gt;-rf&lt;/span&gt; pi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update and upgrade the system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot the system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup hotspot
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create an access point in raspberry pi

 Diagram                                  +- RPi ---------+
                                      +---+ 192.168.10.15 |          +- ESP8266 ---+
                                      |   |     WLAN AP   +-)))  (((-+ WLAN Client |
                                      |   | 192.168.7.1   |          | 192.168.7.x |
                                      |   +---------------+          +-------------+
                                      .
                                      .
                              .
                 +- Router -----+     |
                 | Firewall     |     |   +- PC#2 --------+
(Internet)---WAN-+ DHCP server  +-LAN-+---+ 192.168.10.11 |
                 | 192.168.10.1 |     |   +---------------+
                 +--------------+     |
                                      |   +- PC#1 --------+
                                      +---+ 192.168.10.10 |
                                          +---------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install required packages&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;hostapd dnsmasq netfilter-persistent iptables-persistent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable wireless access point&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl unmask hostapd
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;hostapd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define the wireless interface IP configuration&lt;br&gt;
Configure wlan0 interface in &lt;code&gt;/etc/dhcpcd.conf&lt;/code&gt;&lt;br&gt;
Add the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  interface wlan0
    static ip_address=192.168.7.1/24
    nohook wpa_supplicant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable ip forwarding in &lt;code&gt;/etc/sysctl.conf&lt;/code&gt; and uncomment the following line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; net.ipv4.ip_forward=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allow traffic between clients on this foreign wireless network&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; POSTROUTING &lt;span class="nt"&gt;-o&lt;/span&gt; eth0 &lt;span class="nt"&gt;-j&lt;/span&gt; MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make persistent changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure the DHCP and DNS services for the wireless network&lt;br&gt;
First create a backup&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;/etc/dnsmasq.conf&lt;/code&gt; and add the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  interface=wlan0 
  dhcp-range=192.168.7.2,192.168.7.40,255.255.255.0,24h
  domain=wlan
  address=/gw.wlan/192.168.7.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set WiFi country&lt;br&gt;
Localization Options -&amp;gt; Change WLAN Country -&amp;gt; choose your country -&amp;gt; finish&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;raspi-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure wireless operation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;rfkill unblock wlan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure access point in &lt;code&gt;/etc/hostapd/hostapd.conf&lt;/code&gt;&lt;br&gt;
Add the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  country_code=MX
  interface=wlan0
  ssid=rpi-hotspot
  hw_mode=g
  channel=8
  macaddr_acl=0
  auth_algs=1
  ignore_broadcast_ssid=0
  wpa=2
  wpa_passphrase=rasp-p@s2w0rd
  wpa_key_mgmt=WPA-PSK
  wpa_pairwise=TKIP
  rsn_pairwise=CCMP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot the system and check connection with new access point&lt;/p&gt;

&lt;p&gt;Install &lt;code&gt;python3&lt;/code&gt; and set as default interpreter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; python3
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo rm&lt;/span&gt; /usr/bin/python
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /usr/bin/python3 /usr/bin/python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy &lt;code&gt;pythonServer&lt;/code&gt; to raspberry pi&lt;/p&gt;

&lt;h1&gt;
  
  
  ESP8266 Configurations
&lt;/h1&gt;

&lt;p&gt;Install required packages&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;arduino-cli&lt;/li&gt;
&lt;li&gt;picocom&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install esp8266 arduino core&lt;br&gt;
First add additional boards in &lt;code&gt;~/Arduino/arduino-cli.yml&lt;/code&gt; and add the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# arduino-cli.yaml
board_manager:
  additional_urls:
    - http://arduino.esp8266.com/stable/package_esp8266com_index.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update index&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;arduino-cli &lt;span class="nt"&gt;--config-file&lt;/span&gt; ~/Arduino/arduino-cli.yml core update-index
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Search esp8266 boards&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;arduino-cli &lt;span class="nt"&gt;--config-file&lt;/span&gt; ~/Arduino/arduino-cli.yml core search esp8266
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install esp8266 boards&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;arduino-cli &lt;span class="nt"&gt;--config-file&lt;/span&gt; ~/Arduino/arduino-cli.yml core &lt;span class="nb"&gt;install &lt;/span&gt;esp8266:esp8266
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile and upload the sketch, assuming that port of esp8266 is &lt;code&gt;/dev/ttyUSB0&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;arduino-cli compile &lt;span class="nt"&gt;-b&lt;/span&gt; esp8266:esp8266:nodemcuv2 &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /dev/ttyUSB0 arduinoClient/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Test communications
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qa3JnCud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/t5bw6ges01wmlbyag1pz.GIF" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qa3JnCud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/t5bw6ges01wmlbyag1pz.GIF" alt="testGift" width="500" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Init server in raspberry pi&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python ~/pythonServer/server.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Init serial monitor for &lt;code&gt;esp8266&lt;/code&gt; board&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 115200 /dev/ttyUSB0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Raspberry pi output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Intialize socket server, listen port: 35000
  Connection from: ('192.168.7.17', 59552)
  From connected user: Init connection from ESP8266
  Write response -&amp;gt; hi from server
  From connected user: hi from client
  Write response -&amp;gt; send quit sequence
  Recive disconnect from client
  Close connection...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Arduino output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Wait for WiFi... .....
  WiFi connected
  IP address:
  192.168.7.17
  Connecting to 192.168.7.1:35000
  Wait response from server ...
  Server response: hi from server
  You response -&amp;gt; hi from client
  Server response: send quit sequence
  You response -&amp;gt; quit!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/ivanmorenoj/arduino-wifi-connection"&gt;Source Code&lt;/a&gt;
&lt;/h3&gt;

</description>
      <category>raspberrypi</category>
      <category>esp8266</category>
      <category>wifihotspot</category>
      <category>arduino</category>
    </item>
    <item>
      <title>How to connect raspberry pi with HC-05 bluetooth module + arduino programm</title>
      <dc:creator>Iván Moreno</dc:creator>
      <pubDate>Fri, 14 Aug 2020 20:10:22 +0000</pubDate>
      <link>https://dev.to/ivanmoreno/how-to-connect-raspberry-pi-with-hc-05-bluetooth-module-arduino-programm-3h7a</link>
      <guid>https://dev.to/ivanmoreno/how-to-connect-raspberry-pi-with-hc-05-bluetooth-module-arduino-programm-3h7a</guid>
      <description>&lt;h1&gt;
  
  
  Basic connection between arduino and raspberry pi through Bluetooth
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3twv26009rizz1phmyhc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3twv26009rizz1phmyhc.jpg" alt="setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardware
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry pi 3b+ (it has inbuilt Bluetooth)&lt;/li&gt;
&lt;li&gt;Arduino micro&lt;/li&gt;
&lt;li&gt;HC-05 Bluetooth module&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  System requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;arduino-cli&lt;/li&gt;
&lt;li&gt;picocom&lt;/li&gt;
&lt;li&gt;python 3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurations for Bluetooth module HC-05
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Configure the module as master&lt;/li&gt;
&lt;li&gt;Set PIN&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurations for Raspberry Pi
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ivanmorenoj/arduino-wifi-connection/blob/master/README.md#raspberry-pi-setup" rel="noopener noreferrer"&gt;Install and configure raspbian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ivanmorenoj/arduino-wifi-connection/blob/master/README.md#raspberry-pi-setup" rel="noopener noreferrer"&gt;Configure python3 as default python interpreter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install Bluetooth packages&lt;/li&gt;
&lt;li&gt;Pair with HC-05 module&lt;/li&gt;
&lt;li&gt;Copy Bluetooth code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurations for arduino
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install avr boards&lt;/li&gt;
&lt;li&gt;Make physical connections&lt;/li&gt;
&lt;li&gt;Copy arduino code and upload to arduino board&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  HC-05 Setup
&lt;/h1&gt;

&lt;p&gt;First connect Bluetooth module to USB serial and press EN button, then send AT commands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkoqtlkiryxv19gf5adf1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkoqtlkiryxv19gf5adf1.jpg" alt="at-commands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Test AT commands in serial port from USB to serial converter. The default baud rate for AT commands is 38400&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"AT&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 38400 &lt;span class="nt"&gt;-qrx&lt;/span&gt; 1000 /dev/ttyUSB0
OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set with AT commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"AT+NAME=ARDUINOBT&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 38400 &lt;span class="nt"&gt;-qrx&lt;/span&gt; 1000 /dev/ttyUSB0
OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set password&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"AT+PSWD=1379&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 38400 &lt;span class="nt"&gt;-qrx&lt;/span&gt; 1000 /dev/ttyUSB0
OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set default baud rate&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"AT+UART=115200,1,0&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 38400 &lt;span class="nt"&gt;-qrx&lt;/span&gt; 1000 /dev/ttyUSB0
OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disconnect and test settings&lt;/p&gt;

&lt;h1&gt;
  
  
  Raspberry Pi Setup
&lt;/h1&gt;

&lt;p&gt;Once installed raspbian and make the &lt;a href="https://github.com/ivanmorenoj/arduino-wifi-connection/blob/master/README.md#raspberry-pi-setup" rel="noopener noreferrer"&gt;basic configurations&lt;/a&gt;, install Bluetooth required packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; pi-bluetooth bluetooth bluez picocom blueman python3-pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First edit Bluetooth service in &lt;code&gt;/etc/systemd/system/dbus-org.bluez.service&lt;/code&gt;&lt;br&gt;
Add the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ExecStart=/usr/lib/bluetooth/bluetoothd -C
  ExecStartPost=/usr/bin/sdptool add SP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload systemd units&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable Bluetooth service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; bluetooth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;/etc/modules-load.d/modules.conf&lt;/code&gt; to load rfcomm module automatically &lt;br&gt;
Add the following line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rfcomm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot the system&lt;/p&gt;

&lt;h2&gt;
  
  
  Pair with HC-05 module
&lt;/h2&gt;

&lt;p&gt;Access to Bluetooth console&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;bluetoothctl 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pair with Bluetooth module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]# agent on
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]# scan on
  Discovery started
  &lt;span class="o"&gt;[&lt;/span&gt;NEW] Device 98:D3:31:50:4A:C1 98-D3-31-50-4A-C1
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 LegacyPairing: no
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 Name: ARDUINOBT
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 Alias: ARDUINOBT

&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]# scan off
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Controller B8:27:EB:80:2D:06 Discovering: no
  Discovery stopped

&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]# pair 98:D3:31:50:4A:C1
  Attempting to pair with 98:D3:31:50:4A:C1
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 Connected: &lt;span class="nb"&gt;yes
  &lt;/span&gt;Request PIN code
  &lt;span class="o"&gt;[&lt;/span&gt;agent] Enter PIN code: 1379
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 UUIDs: 00001101-0000-1000-8000-00805f9b34fb
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 ServicesResolved: &lt;span class="nb"&gt;yes&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 Paired: &lt;span class="nb"&gt;yes
  &lt;/span&gt;Pairing successful
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 ServicesResolved: no
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 Connected: no

&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]# trust 98:D3:31:50:4A:C1
  &lt;span class="o"&gt;[&lt;/span&gt;CHG] Device 98:D3:31:50:4A:C1 Trusted: &lt;span class="nb"&gt;yes
  &lt;/span&gt;Changing 98:D3:31:50:4A:C1 trust succeeded

&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]# &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a serial device&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;rfcomm &lt;span class="nb"&gt;bind &lt;/span&gt;rfcomm0 &amp;lt;device&lt;span class="s1"&gt;'s MAC&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything works, connect with picocom and test communication in both sides&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft0gmjjql0n35nca49odj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft0gmjjql0n35nca49odj.gif" alt="check-connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install pyserial library for python3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;pyserial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy pythonClient dir to raspberry pi and execute &lt;code&gt;client.py&lt;/code&gt; script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python pythonClient/client.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Arduino Setup
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Physical connections
&lt;/h2&gt;

&lt;p&gt;Connections for HC-05 module&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GND -&amp;gt; GND Arduino&lt;/li&gt;
&lt;li&gt;VCC -&amp;gt; VCC Arduino&lt;/li&gt;
&lt;li&gt;RX  -&amp;gt; D14 Arduino&lt;/li&gt;
&lt;li&gt;TX  -&amp;gt; D15 Arduino&lt;/li&gt;
&lt;li&gt;EN  -&amp;gt; N/C&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Compile and upload the sketch
&lt;/h2&gt;

&lt;p&gt;Upload the code to arduino board, considering serial port of arduino micro is &lt;code&gt;/dev/ttyACM0&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;arduino-cli compile &lt;span class="nt"&gt;-b&lt;/span&gt; arduino:avr:micro &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /dev/ttyACM0 arduinoBT-HC05/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Test Communications
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8dvpi1erz1dkdwcte404.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8dvpi1erz1dkdwcte404.gif" alt="test-arduino-connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Raspberry pi output example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;developer@raspberrypi:~ $ python pythonClient/client.py
  Enter your message below.
  Insert "exit" to leave the application.
  You message &amp;gt;&amp;gt; hi from raspberry pi
  Server Response &amp;gt;&amp;gt; hi

  You message &amp;gt;&amp;gt; test connection
  Server Response &amp;gt;&amp;gt; test connection from arduino

  You message &amp;gt;&amp;gt; exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Arduino Output example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ picocom -b 115200 /dev/ttyACM0
  Terminal ready
  Server response: hi from raspberry pi
  You response -&amp;gt; hi
  Server response: test connection
  You response -&amp;gt; test connection from arduino

  Terminating...
  Skipping tty reset...
  Thanks for using picocom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/ivanmorenoj/rpi-bluetooth-arduino" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;
&lt;/h3&gt;

</description>
      <category>raspberrypi</category>
      <category>arduino</category>
      <category>hc05</category>
      <category>bluetooth</category>
    </item>
  </channel>
</rss>
