<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on xmatthias blog</title>
    <link>https://blog.xmatthias.com/post/</link>
    <description>Recent content in Posts on xmatthias blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 08 Dec 2023 19:00:00 +0000</lastBuildDate><atom:link href="https://blog.xmatthias.com/post/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Debugging a pytest segfault</title>
      <link>https://blog.xmatthias.com/post/pytest-debug-segfault/</link>
      <pubDate>Fri, 08 Dec 2023 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/pytest-debug-segfault/</guid>
      
      <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;A recent update of &lt;a href=&#34;https://pytorch.org/&#34;&gt;pytorch&lt;/a&gt; (update from 2.0.1 to 2.1.1) broke the windows pytest CI runs of the project I maintain, &lt;a href=&#34;https://freqtrade.io&#34;&gt;Freqtrade&lt;/a&gt;.
Pytest itself showed nothing helpful beyond a few warnings.
All tests were passing, yet the CI step was failing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;pytest_ci_failure.png&#34; alt=&#34;Pytest having all files pass, but CI fail&#34;&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s however a great opportunity to learn how to approach such issues.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer&lt;/em&gt; This Post will be quite technical and should hence be considered advanced content. I&amp;rsquo;ll assume basic understanding of pytest, too.&lt;/p&gt;
&lt;h2 id=&#34;reproducing-the-problem&#34;&gt;Reproducing the problem&lt;/h2&gt;
&lt;p&gt;The initial failure happened on windows - but setting the same &amp;ldquo;random state&amp;rdquo; to all systems quickly showed that also MacOS / linux behave identically with a specific sequence.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;pytest_ci_failure_linux.png&#34; alt=&#34;Pytest having all files pass, but CI fail with Segmentation fault&#34;&gt;&lt;/p&gt;
&lt;p&gt;The linux output was slightly more helpful by providing a &lt;code&gt;Segmentation fault      (core dumped)&lt;/code&gt; output.
Yet pytest did not provide any information on the test causing this, nor any further hint about where of what might be happening.&lt;/p&gt;
&lt;p&gt;To start debugging this in github actions, i added the following action step after each of the test steps.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Setup tmate session&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;if&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;failure()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;mxschmitt/action-tmate@v3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This allows me to ssh into each of the Actions, and perform an analysis on the affected system.
While time is limited to ~6h (the maximum execution time on github Actions) - that&amp;rsquo;s plenty of time to run a few test.&lt;/p&gt;
&lt;p&gt;I could rather quickly confirm that the problem happens only with &lt;code&gt;torch==2.1.1&lt;/code&gt;. &lt;code&gt;torch==2.0.1&lt;/code&gt; did not show the error, and tests were working perfectly fine.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&#34;https://github.com/pytest-dev/pytest/issues/88410&#34;&gt;pytest issue&lt;/a&gt; from 2021 showed that an older pytorch version had similar problems. While it didn&amp;rsquo;t really offer a solution, it did offer the following command to get to the traceback of the segfault&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 -X faulthandler -m pytest -p no:faulthandler
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This disables the pytest error-hander (&lt;code&gt;faulthandler&lt;/code&gt;), and reverts to the faulthandler built into python.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 -X faulthandler -m pytest --random-order-seed &lt;span style=&#34;color:#ae81ff&#34;&gt;208417&lt;/span&gt; -p no:faulthandler
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(the actual random state is not relevant, but this seed happened to cause the problem initially).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;pytest_segfault_with_traceback.png&#34; alt=&#34;Pytest segfault with traceback&#34;&gt;&lt;/p&gt;
&lt;p&gt;This allowed me to pinpoint the problem to some part of the cleanup code.
What&amp;rsquo;s odd here is the fact that the actual error seems to come from the logging module.&lt;/p&gt;
&lt;p&gt;The code itself (&lt;code&gt;__del__()&lt;/code&gt; calling &lt;code&gt;close()&lt;/code&gt; - which adds log messages) was at this point multiple years old, and never caused any problem (neither during tests, neither during regular executions).&lt;/p&gt;
&lt;p&gt;At this point, i was still testing with the full test suite - which took around 5 minutes before exiting. The error also happened about 5-10 seconds after the last output from pytest (which might be a tell-tale sign).
Not a great situation to be debugging this.&lt;/p&gt;
&lt;h2 id=&#34;reducing-the-test-size&#34;&gt;Reducing the test size&lt;/h2&gt;
&lt;p&gt;By this point, i was able to reproduce the same issue locally - which simplified the further steps.&lt;/p&gt;
&lt;p&gt;However, the failure did not happen without changing the test execution sequence to something random - hence I needed some way to keep the problematic test sequence, while still reducing the number of tests that run.&lt;/p&gt;
&lt;p&gt;Pytest allows us to collect the tests that will be running.
Hence we can pipe this output into a file, which we&amp;rsquo;ll slowly reduce until only a few tests are left.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pytest --random-order-seed 208417  --collect-only -q &amp;gt; base_torch_tests.txt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We need to open the file and remove the final 2 lines (it&amp;rsquo;s important that there is no empty line at the end, otherwise the full test-suite will run again after the tests in the file).&lt;/p&gt;
&lt;p&gt;We can then use a quite handy xargs script to run the tests in the file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xargs -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; pytest -v &amp;lt; torch_tests_base.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;for MacOS, you&amp;rsquo;ll need a slightly different command, as xargs on Mac doesn&amp;rsquo;t have a &lt;code&gt;-d&lt;/code&gt; option.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat torch_tests_base.txt | tr &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt; | xargs -0 pytest -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we move through the following steps until only 2 tests are left&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;modify the file, removing tests&lt;/li&gt;
&lt;li&gt;rerun above command&lt;/li&gt;
&lt;li&gt;repeat&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The method in this section is taken from Anthony Sottile&amp;rsquo;s [Youtube Video](reducing the amount of tests), which explains the whole process in greater detail.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;
&lt;p&gt;Once only 2 tests were left, i tried to get behind what might be causing a failure out of the logging module.&lt;/p&gt;
&lt;p&gt;The odd thing about the tests:
The first test must somehow import torch (it didn&amp;rsquo;t even use torch, just imported a file which happened to import torch)
The 2nd test was completely unrelated to torch - but both touched the &lt;code&gt;__del__()&lt;/code&gt; method we saw above.&lt;/p&gt;
&lt;p&gt;Removing the log line, no segfault (so it&amp;rsquo;s related to the logging module).&lt;/p&gt;
&lt;p&gt;As we only import torch - the next step is to analyze what torch is actually doing when it&amp;rsquo;s imported (&lt;em&gt;spoiler&lt;/em&gt;: a &lt;strong&gt;lot&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;The offending code is in the &lt;a href=&#34;https://github.com/pytorch/pytorch/blob/4c55dc50355d5e923642c59ad2a23d6ad54711e7/torch/__init__.py#L1835-L1836&#34;&gt;torch &lt;code&gt;__init__.py&lt;/code&gt; file&lt;/a&gt; - which &amp;ldquo;initializes logging&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;torch_logging.png&#34; alt=&#34;Torch init.py - last 2 lines&#34;&gt;&lt;/p&gt;
&lt;p&gt;I tried to dig a bit deeper into &lt;strong&gt;what&lt;/strong&gt; this is actually doing that&amp;rsquo;s causing logging to fail at a later point, but I&amp;rsquo;m still at a loss (Please get in touch if you happen to know the reason).&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;quick and dirty&amp;rdquo; fix for this problem is to mock the torch init_logs function during test executions.
By marking the pytest fixture as &lt;code&gt;autouse=True&lt;/code&gt;, it&amp;rsquo;s automatically used for all tests.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@pytest.fixture&lt;/span&gt;(autouse&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;patch_torch_initlogs&lt;/span&gt;(mocker) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mocker&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;patch(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;torch._logging._init_logs&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While that&amp;rsquo;s not an ideal solution - it&amp;rsquo;s a test-problem only, hence justifies a test-only solution.&lt;/p&gt;
&lt;p&gt;The Final fix looked slightly different due to another problem on MacOS.
Tests involving Torch on this platform were already disabled - so we now mock the whole module to avoid failures due to importing this.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@pytest.fixture&lt;/span&gt;(autouse&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;patch_torch_initlogs&lt;/span&gt;(mocker) &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; is_mac():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# Mock torch import completely&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; sys
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; types
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        module_name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;torch&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        mocked_module &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; types&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ModuleType(module_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sys&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;modules[module_name] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; mocked_module
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        mocker&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;patch(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;torch._logging._init_logs&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;wrapping-up&#34;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;This whole investigation took quite a few hours out of my week, but was well worth my time.
I learned quite a lot (how to debug in github actions, how to debug segfaults that pytest &amp;ldquo;hides&amp;rdquo;, how badly some libraries treat the python environment).&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Migrating from ghost to hugo in 2023</title>
      <link>https://blog.xmatthias.com/post/migrate-to-hugo/</link>
      <pubDate>Sat, 23 Sep 2023 18:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/migrate-to-hugo/</guid>
      
      <description>&lt;h2 id=&#34;reasons&#34;&gt;Reasons&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been running this blog on a self-hosted ghost platform ever since the very first post.
Over time, ghost served me well - and this is not a decision against ghost, but for a simplified site setup.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been eyeing at &lt;a href=&#34;https://gohugo.io/&#34;&gt;hugo&lt;/a&gt; for some time now. As it builds a static webpage, there are tons of hosting options (free and paid).
To me, this provides the benefit of being able to decomission the server I used to run the blog on.&lt;/p&gt;
&lt;p&gt;In this blogpost, I&amp;rsquo;ll outline the steps I took to migrate the existing content to the new blog.&lt;/p&gt;
&lt;h2 id=&#34;initial-setup&#34;&gt;Initial setup&lt;/h2&gt;
&lt;p&gt;To get started, I used &lt;a href=&#34;https://github.com/ellie/ghostToHugo/tree/ellie/update-sys&#34;&gt;ghostToHugo&lt;/a&gt; - a fork of the original ghostToHugo project, to convert all posts in Ghost to Hugo templates.&lt;/p&gt;
&lt;p&gt;This is as easy as creating an export from the ghost admin panel (&lt;code&gt;Settings -&amp;gt; labs -&amp;gt; &amp;quot;Export your content&amp;quot;&lt;/code&gt;) and downloading the resulting &lt;code&gt;.json&lt;/code&gt; file.
We then run &lt;code&gt;ghostToHugo -p ~/mysite export.json&lt;/code&gt; - which creates a hugo project for us.&lt;/p&gt;
&lt;p&gt;Next, I took an existing &lt;a href=&#34;https://themes.gohugo.io/themes/hugo-blog-awesome/&#34;&gt;simple theme&lt;/a&gt; and configured this for my new hugo project&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/hugo-sid/hugo-blog-awesome.git themes/hugo-blog-awesome
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We then add this theme to our &lt;code&gt;hugo.toml&lt;/code&gt; file as &lt;code&gt;theme = &amp;quot;hugo-blog-awesome&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At this point, we already have an initial page up and running, which we can start with &lt;code&gt;hugo server&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;update-links-and-assets&#34;&gt;Update links and assets&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s worth pointing out that links between posts won&amp;rsquo;t work at this point, nor will images render correctly.&lt;/p&gt;
&lt;p&gt;Inspecting one of the posts, it becomes immediately clear why - ghost&amp;rsquo;s export added a &lt;code&gt;__GHOST_URL__&lt;/code&gt; in front of all links.
&lt;code&gt;[link](__GHOST_URL__/duplicity_remote/)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We can fix this pretty easily by removing all occurances of &lt;code&gt;__GHOST_URL__/&lt;/code&gt; (for the above case, this leaves &lt;code&gt;[link](duplicity_remote/)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Images have a similar behavior - though slightly more complicated, as ghost stores them as follows:
&lt;code&gt;![onedrive_oauth1](__GHOST_URL__/content/images/2023/08/some_image.png)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;As I like to keep the post and corresponding image together, I used the following approach (shown on the example of a fictionary post &lt;code&gt;hello-world.md&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a directory next to the &lt;code&gt;hello-world.md&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Move the file into the directory.&lt;/li&gt;
&lt;li&gt;Move corresponding image files into the directory (i happened to have the original files still in a backup repository).&lt;/li&gt;
&lt;li&gt;Replace image sources.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir content/post/hello-world/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv content/post/hello-world.md content/post/hello-world/index.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv ../imagesource/hello-world.jpg content/post/hello-world/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now replace the link to be a relative link:
&lt;code&gt;![onedrive_oauth1](__GHOST_URL__/content/images/2017/10/some_image.png)&lt;/code&gt; -&amp;gt; &lt;code&gt;![onedrive_oauth1](some_image.png)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We obviously have to repeat this for every blogpost with images.
The resulting structure is a mix of directories (posts with images) and standalone posts (posts without images).&lt;/p&gt;
&lt;h3 id=&#34;update-post-header&#34;&gt;Update Post header&lt;/h3&gt;
&lt;p&gt;Out of the conversion, all posts had a header as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;+++
date = 2023-08-03T11:30:00Z
description = &amp;#34;&amp;#34;
draft = false
slug = &amp;#34;hello-world&amp;#34;
title = &amp;#34;hello world&amp;#34;
summary = &amp;#34;Hello world blog post&amp;#34;
tags = [&amp;#34;personal&amp;#34;]
+++
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;While this is a good first step - it&amp;rsquo;s not ideal. The description was empty in all cases - however many posts had a summary.&lt;/p&gt;
&lt;p&gt;A quick look at the Lighthouse benchmark revealed that the posts were missing a &amp;ldquo;description&amp;rdquo; field (your experience may vary depending on the selected theme).&lt;/p&gt;
&lt;p&gt;As a quick fix, I&amp;rsquo;ve simply copied the content of &amp;ldquo;summary&amp;rdquo; to &amp;ldquo;description&amp;rdquo; - as that seemed to be fitting in most instances.&lt;/p&gt;
&lt;p&gt;Final heading:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;+++
date = 2023-08-03T11:30:00Z
description = &amp;#34;Hello world blog post&amp;#34;
draft = false
slug = &amp;#34;hello-world&amp;#34;
title = &amp;#34;hello world&amp;#34;
summary = &amp;#34;Hello world blog post&amp;#34;
tags = [&amp;#34;personal&amp;#34;]
+++
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;url-changes&#34;&gt;URL changes&lt;/h3&gt;
&lt;p&gt;My existing ghost blog was using url&amp;rsquo;s as follows: &lt;code&gt;https://blog.xmatthias.com/hello-world/&lt;/code&gt;. Hugo by default inserts a &lt;code&gt;/post&lt;/code&gt; in the middle, so the url becomes &lt;code&gt;https://blog.xmatthias.com/post/hello-world/&lt;/code&gt;.
That&amp;rsquo;s not a problem, but requires some attention, which means we have to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add redirects - ideally as 301 (hugo-style redirects will hurt SEO).&lt;/li&gt;
&lt;li&gt;Migrate url&amp;rsquo;s on a comment platform (in my case, &lt;a href=&#34;https://disqus.com&#34;&gt;disqus&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;redirects&#34;&gt;Redirects&lt;/h4&gt;
&lt;p&gt;As i&amp;rsquo;m going to deploy my hugo page on cloudflare pages, I can use the &lt;a href=&#34;https://developers.cloudflare.com/pages/platform/redirects/&#34;&gt;redirects feature&lt;/a&gt; - which is as simple as a &lt;code&gt;_redirects&lt;/code&gt; file in the static directory (&lt;code&gt;/static/_redirects&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;I have the following rules.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/rss/ /post/index.xml 200
/rss /rss/ 301
# Redirect from old post addresses
/hello-world /post/hello-world/ 301
/hello-world/ /post/hello-world/ 301
# ... (continued for all posts)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The first 2 lines are there to ensure the RSS url remains the same, available under &lt;code&gt;blog.xmatthias.com/rss/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;All posts will receive a permanent redirect (301) - which will allow SEO to continue to work, as the new page is treated identically to the prior page.&lt;/p&gt;
&lt;h4 id=&#34;disqus--comment-system&#34;&gt;Disqus / comment system&lt;/h4&gt;
&lt;p&gt;For disqus, there&amp;rsquo;s a few &amp;ldquo;migration tools&amp;rdquo;.
Right after putting the new page live, i verified that all redirects work - and then tried to use the &amp;ldquo;Redirect Crawler&amp;rdquo;.
Unfortunately, it didn&amp;rsquo;t yield the expected results - which led me to the URL mapper.&lt;/p&gt;
&lt;p&gt;This takes a plain csv file with &lt;code&gt;from,to&lt;/code&gt; format - so for our sample post, it looked as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;https://blog.xmatthias.com/hello-world/,https://blog.xmatthias.com/post/hello-world/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This format is very similar to the one used in &lt;code&gt;_redirects&lt;/code&gt; - and required only some changes.
Saving and uploading the file gave me a confirmation box (so i could check my redirects).&lt;/p&gt;
&lt;p&gt;After confirming that this was working, the comments started to imediately pop up on the new page.&lt;/p&gt;
&lt;h2 id=&#34;closing&#34;&gt;Closing&lt;/h2&gt;
&lt;p&gt;In total (including learning hugo, and the most timeconsuming task, picking a theme), this took me about 3-4 hours over the course of a few days.&lt;/p&gt;
&lt;p&gt;This was sufficient for me to put the blog out into the wild - though this wasn&amp;rsquo;t all - and after changing the blog engine, I did some further updates (Theme adjustments, adding security headers).
This will however be a topic for another blog post.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity - Backblaze</title>
      <link>https://blog.xmatthias.com/post/duplicity-backblaze/</link>
      <pubDate>Sat, 26 May 2018 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-backblaze/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I would recommend to head over to the &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post, but is required for the tutorial to work).
You should also have a look at the &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains an overview of this series.
The basic configuration from &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used as basis in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;backblaze&#34;&gt;Backblaze&lt;/h2&gt;
&lt;p&gt;To start with, we will need an account at &lt;a href=&#34;https://www.backblaze.com&#34;&gt;Backblaze&lt;/a&gt;. Once we&amp;rsquo;re setup (verified the account via phone) and have configured 2FA (you do use 2FA, don&amp;rsquo;t you?) we can get started. We&amp;rsquo;ll get 10G Storage for free, free upload and 1Gb free download, just for signing up. This will be enough to get started using backups, and evaluate if this is the right service.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&#34;https://www.backblaze.com&#34;&gt;Backblaze&lt;/a&gt; offers a very good &lt;a href=&#34;https://help.backblaze.com/hc/en-us/articles/115001518354-How-to-configure-Backblaze-B2-with-Duplicity-on-Linux&#34;&gt;tutorial&lt;/a&gt; on how to get duplicity setup under Linux, I&amp;rsquo;ll not repeat these steps here.&lt;/p&gt;
&lt;p&gt;Rather, we&amp;rsquo;ll jump right in and include Backblaze into the &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity-backup.sh&lt;/a&gt; script, we used &lt;a href=&#34;../duplicity_backup_script&#34;&gt;previously&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;duplicity-backupsh&#34;&gt;duplicity-backup.sh&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;The following will assume that Backblaze has been setup and tested successfully using the &lt;a href=&#34;https://help.backblaze.com/hc/en-us/articles/115001518354-How-to-configure-Backblaze-B2-with-Duplicity-on-Linux&#34;&gt;Backblaze tutorial&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Should you have problems with the above Tutorial and getting setup let me know in the comments down below and I&amp;rsquo;ll update this post to include these steps.&lt;/p&gt;
&lt;h3 id=&#34;single-site-backup&#34;&gt;Single site Backup&lt;/h3&gt;
&lt;p&gt;To backup to Backblaze using the &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity-backup.sh&lt;/a&gt; script we used &lt;a href=&#34;../duplicity_backup_script&#34;&gt;previously&lt;/a&gt;, change &lt;code&gt;DEST&lt;/code&gt; to the following  to the script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# DEST=&amp;#34;b2://&amp;lt;accountid&amp;gt;:&amp;lt;Application key&amp;gt;@&amp;lt;bucket name&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DEST&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;b2://431b5d5zd3ac:dad74350dabd8d9b47ca3bc7094c784339c8452d8f@duplicitytest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Don&amp;rsquo;t even mind trying using the above line without inserting your own id/key - this is not my account (and a randomized key).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We now run the duplicity-backup.sh script.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --backup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please note that this method is not recommended as the backup is in only one place. Depending on the requirements, the following approach should be preferred.&lt;/p&gt;
&lt;h3 id=&#34;multi-site-backup&#34;&gt;Multi-site Backup&lt;/h3&gt;
&lt;p&gt;As explained in &lt;a href=&#34;../duplicity-multisite-backup&#34;&gt;this&lt;/a&gt; article, we can simply add backup-locations by appending them to the configuration file.&lt;/p&gt;
&lt;p&gt;Remember how we configured our &lt;code&gt;DEST&lt;/code&gt; variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DEST&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#34;multi:///home/matt/multiconfig.conf?mode=mirror&amp;amp;onfail=abort&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This mirrors all backups to all configured sites, and fails if one is not available.
Now, open the file configured above and insert the Backblaze configuration&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Local disk test&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file:///home/matt/backupmulti&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backblaze test&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;b2://431b5d5zd3ac:dad74350dabd8d9b47ca3bc7094c784339c8452d8f@duplicitytest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As I already had a backup from previous backups, we need to upload the existing backups first. This way, we won&amp;rsquo;t loose any backup-history.
This can be accomplished by running the following command (please make sure to update both account-id, keys and bucket name to suit your needs)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Insert required account-id and application key when asked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;b2 authorize-account
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd &amp;lt;existingbackupdir&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Sync the backup-folder to the duplicity-bucket &amp;#34;duplicitytest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;b2 sync . b2://duplicitytest/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way, we keep our history as well.&lt;/p&gt;
&lt;h2 id=&#34;closing-words&#34;&gt;Closing words&lt;/h2&gt;
&lt;p&gt;There are a a ton of of options for cloud backups. &lt;a href=&#34;https://www.backblaze.com&#34;&gt;Backblaze&lt;/a&gt; is one of them (and for now, my backup provider of choice). The speed is good (something I complained about in my &lt;a href=&#34;../duplicity-hubic&#34;&gt;Hubic&lt;/a&gt; Tutorial).
Also the security seems good, and people I trust security-wise like &lt;a href=&#34;https://www.troyhunt.com/weekly-update-84/&#34;&gt;Troy Hunt&lt;/a&gt; trust Backblaze with their data.&lt;/p&gt;
&lt;p&gt;In the end, it does not matter all that much which provider is used, as long as the backup is executed regularly, tested and implemented following the &amp;ldquo;3-2-1&amp;rdquo; rule:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;3 total copies of the data - on 2 different mediums, at least 1 off site.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;full-disclosure&#34;&gt;Full disclosure&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Title photo credit:&lt;/strong&gt; &lt;a href=&#34;http://www.flickr.com/photos/8558461@N08/6073913225&#34;&gt;ChrisDag&lt;/a&gt; via &lt;a href=&#34;http://photopin.com&#34;&gt;photopin&lt;/a&gt; &lt;a href=&#34;https://creativecommons.org/licenses/by/2.0/&#34;&gt;(license)&lt;/a&gt;&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Contributing to Open Source</title>
      <link>https://blog.xmatthias.com/post/contributing-to-open-source/</link>
      <pubDate>Sat, 14 Apr 2018 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/contributing-to-open-source/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve been very quiet on this blog recently, mainly because I was trying to get started contributing to Open Source projects. I wanted to start giving back for a very long time, but never got around to actually start contributing regularly.&lt;/p&gt;
&lt;p&gt;This all got started by Troy Hunt &lt;a href=&#34;https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/&#34;&gt;introducing Pwned Passwords v2&lt;/a&gt; back in February. The same night, right after reading Troy&amp;rsquo;s article, I quickly spun up a &lt;a href=&#34;https://github.com/xmatthias/pywnedpasswords&#34;&gt;python project&lt;/a&gt; leveraging the &lt;a href=&#34;https://en.wikipedia.org/wiki/K-anonymity&#34;&gt;K-Anonymity method&lt;/a&gt; and checking for compromised passwords offline. While refactoring the project to upload it to &lt;a href=&#34;https://pypi.python.org/pypi/pywnedpasswords&#34;&gt;pypi&lt;/a&gt;, I introduced a nasty bug causing the script to stop functioning. A few days later, I found a Pull Request in my repository, fixing the bug and repairing what I had broken.
The simplicity of doing this amazed me - I merged the PR, released a new version and decided that I should finally find a project I can contribute to myself.&lt;/p&gt;
&lt;p&gt;A few days later, I stumbled upon a project to which I since contribute regularly. It&amp;rsquo;s only been a few months, but I feel that I&amp;rsquo;m going to keep working on this project for a while - as I really love the code-base and direction the Project is moving to.
I do link to the project below - but I don&amp;rsquo;t think it&amp;rsquo;s important which project it is, as this article is about &lt;strong&gt;contributing to Open Source&lt;/strong&gt;, not about which project i picked.&lt;/p&gt;
&lt;h2 id=&#34;how-to-get-started&#34;&gt;How to get started&lt;/h2&gt;
&lt;h3 id=&#34;picking-a-project&#34;&gt;Picking a project&lt;/h3&gt;
&lt;p&gt;In order to get started, you needed a project to contribute to.
My main selection criteria are below:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a small to medium size project, which already has multiple contributors (only one contributor might mean that he is not open to contributions), but not too many (huge projects mostly have also a huge code-base.&lt;/li&gt;
&lt;li&gt;the code base shouldn&amp;rsquo;t be too big, so getting into it does not take weeks or months.&lt;/li&gt;
&lt;li&gt;It should be in a language I am familiar with and actively use (this way, I can get the most out of it for myself, as it&amp;rsquo;s both practicing what I know, and learning new stuff as other developers will tackle problems differently).&lt;/li&gt;
&lt;li&gt;I should be using the project myself either now or in the future, otherwise I&amp;rsquo;ll loose interest soon (my goal was/is to get actively involved longer term - not do one-off contributions).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I was not actively searching for a project, but stumbled upon a very &lt;a href=&#34;https://github.com/freqtrade/freqtrade&#34;&gt;interesting project&lt;/a&gt;, which happens to be &lt;em&gt;freqtrade&lt;/em&gt; - a Trading Bot written in Python, with a few core members, a good community contributing and bringing the project forward, doing very good code reviews on pull requests (which I feel is important, as it helps bring my own coding to the next level) and a good test-suite.&lt;/p&gt;
&lt;h2 id=&#34;what-is-in-it-for-me&#34;&gt;What is in it for me&lt;/h2&gt;
&lt;p&gt;While working in Open Source does require some spare time, I feel that the time is a good investment.
It allows me do what I love, while also collaborating with others doing what they love. This project was actually a very fortunate pick, as it brings together programmers with traders, which happen to understand the market, so I was able to get some different views on the same topic, which should help me seeing the business case for the applications I work on in my Job.&lt;/p&gt;
&lt;h3 id=&#34;having-my-code-reviewed&#34;&gt;Having my code reviewed&lt;/h3&gt;
&lt;p&gt;By far the best thing is to have your code extensively reviewed and commented on. This exposure may seem intimidating at first, but its one of the best things in open source. Someone is thinking about what I wrote, trying to understand it, and may help get it corrected - or show a better way to accomplish the same thing.&lt;/p&gt;
&lt;h3 id=&#34;doing-code-reviews&#34;&gt;Doing code reviews&lt;/h3&gt;
&lt;p&gt;I also helped in reviewing code myself, which thought me a lot by understanding how others tackle a problem, discussing the solution in case of doubt and helping others by providing a different view on a problem. Even if you don&amp;rsquo;t comment on a PR, still read through the code, try to understand the intention of the changes, it&amp;rsquo;ll help in understanding the project (and the direction the project is moving towards).&lt;/p&gt;
&lt;h3 id=&#34;patience&#34;&gt;Patience&lt;/h3&gt;
&lt;p&gt;Contributing to Open Source will require patience. I read this before, but it&amp;rsquo;s absolutely true, so when I did my first contribution, I didn&amp;rsquo;t even expect it to be merged (it was merged, after doing a few modifications which came out from the Code Review).
After submitting your first Pull Request, you will need patience. Core contributers may not be around immediately to review your code. It may take days, weeks or months depending on the size of the project until your PR is (eventually) merged or reviewed - and there is nothing you can do about this.&lt;/p&gt;
&lt;h3 id=&#34;testing&#34;&gt;Testing&lt;/h3&gt;
&lt;p&gt;While working on this Project, I got exposed to &lt;a href=&#34;https://pytest.org&#34;&gt;pytest&lt;/a&gt; for the first time. I had heard about it a few times already, but never got a chance to actually use it. This project gave me the chance to do so, with a good base to start with (reading the code already in the repository). It does not matter which test-framework is used in the end - but having good tests is very important to not introduce regressions.&lt;/p&gt;
&lt;h2 id=&#34;wrapping-up&#34;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;I will definitely continue to contribute to Open Source Projects. Time will not always allow me to contribute at the same pace, but that&amp;rsquo;s fine. I am not forced to do any of this, but I still try to help because I like doing it, and I can learn new things by contributing.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re a developer, trying to learn new things every day, you should try to contribute to open-source projects as well (if you&amp;rsquo;re not doing that already). Many projects have a good community (if they don&amp;rsquo;t, consider finding an alternative project) and there is always something new to learn (or someone to be taught something new). Learning new things by doing Courses or reading articles is important too, but it&amp;rsquo;s equally (if not more) important to apply the knowledge - that&amp;rsquo;s what will benefit you the most.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity - multi-site backup</title>
      <link>https://blog.xmatthias.com/post/duplicity-multisite-backup/</link>
      <pubDate>Sat, 17 Feb 2018 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-multisite-backup/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I would recommend to head over to the &lt;a href=&#34;../duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;../duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post, but is required for the tutorial to work).
You should also have a look at the &lt;a href=&#34;../duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains a list of all posts in this series.
The basic configuration from &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used as basis in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;multi&#34;&gt;Multi&lt;/h2&gt;
&lt;p&gt;In this part of the duplicity series, we will try to combine several backup services into the same duplictiy backup job by using the &lt;a href=&#34;http://duplicity.nongnu.org/duplicity.1.html&#34;&gt;duplicity&lt;/a&gt; multi backend. When setup correctly, duplicity will fulfill the &lt;em&gt;3-2-1 backup strategy&lt;/em&gt; all by itself, by doing one backup on the local system, and one (or more!) to remote / cloud systems.&lt;/p&gt;
&lt;p&gt;This backend allows duplicity to use multiple backend storages at the same time, either by extending storage (&lt;code&gt;mode=stripe&lt;/code&gt;) or by mirroring the same backup to all configured backups (&lt;code&gt;mode=mirror&lt;/code&gt;). I will be focusing on the mirror-setup in this post, as this makes the most sense from a security/backup perspective. Stripe-setup is only useful if there is a lot of data to backup with not enough space on one cloud service (while increasing the risk of corrupted backups).&lt;/p&gt;
&lt;h3 id=&#34;basic-configuration&#34;&gt;basic configuration&lt;/h3&gt;
&lt;p&gt;To get started, we use a very basic json-based configuration:
Filename: &lt;code&gt;/home/matt/multiconfig.conf&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Local disk test&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file:///home/matt/backupmulti&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This setup will be almost identical to the &lt;a href=&#34;../duplicity_getting_started&#34;&gt;initial post&lt;/a&gt;, where we ran the backup locally.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s run this once:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB --ssh-askpass /home/matt/test/ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;multi:///home/matt/multiconfig.conf&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When asked, insert your pass-phrases.&lt;/p&gt;
&lt;p&gt;The output should look similar to mine:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB --ssh-askpass /home/matt/test/ &amp;#34;multi:///home/matt/multiconfig.conf?mode=mirror&amp;amp;onfail=abort&amp;#34;
Local and Remote metadata are synchronized, no sync needed.
Last full backup date: none
GnuPG passphrase for decryption:
GnuPG passphrase for signing key:
No signatures found, switching to full backup.
--------------[ Backup Statistics ]--------------
StartTime 1518857776.80 (Sat Feb 17 09:56:16 2018)
EndTime 1518857777.17 (Sat Feb 17 09:56:17 2018)
ElapsedTime 0.37 (0.37 seconds)
SourceFiles 61
SourceFileSize 45086 (44.0 KB)
NewFiles 61
NewFileSize 45086 (44.0 KB)
DeletedFiles 0
ChangedFiles 0
ChangedFileSize 0 (0 bytes)
ChangedDeltaSize 0 (0 bytes)
DeltaEntries 61
RawDeltaSize 30 (30 bytes)
TotalDestinationSizeChange 1539 (1.50 KB)
Errors 0
-------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Checking the folder we configured in the json-file above (&lt;code&gt;/home/matt/backupmulti&lt;/code&gt; in my case) we can see that the backup was made into this folder.&lt;/p&gt;
&lt;p&gt;Before moving to configuring a second backup site, delete the local backup (duplicity will not handle synchronizing files across multiple backup sites, so we either need to copy the existing backups to the remote backup location, or start fresh).&lt;/p&gt;
&lt;p&gt;As we are just getting started, we can easily delete and backup again. If you already have a backup history, consider moving the existing files to all configured locations.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm /home/matt/backupmulti/*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, let&amp;rsquo;s extend the json with a remote-site. I use the configuration from the &lt;a href=&#34;../duplicity_remote/&#34;&gt;initial remote backup post&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Local disk test&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file:///home/matt/backupmulti&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backup to sftp site&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sftp://matt@backupserver:1234//home/matt/offsitebackup_multi&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We simply added a second entry to the configuration file, backing up to a remote site. Let&amp;rsquo;s run this again.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB --ssh-askpass /home/matt/test/ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;multi:///home/matt/multiconfig.conf?mode=mirror&amp;amp;onfail=abort&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that this time i added &lt;code&gt;?mode=mirror&amp;amp;onfail=abort&lt;/code&gt; to the end of the configuration (quoting is necessary now!). This tells duplicity to fail should one of the backups not work correctly. Combine this with one of the &lt;a href=&#34;../duplicity-backup-email-notifications/&#34;&gt;notification&lt;/a&gt; &lt;a href=&#34;../duplicity-backup-ifttt-notifications&#34;&gt;posts&lt;/a&gt; and we will be notified if the backup did not work.
Now, let&amp;rsquo;s check both our locally configured folder, as well as the remote folder. As i deleted the backup from the first try, the folders are now identical.&lt;/p&gt;
&lt;h2 id=&#34;duplicity-backupsh&#34;&gt;duplicity-backup.sh&lt;/h2&gt;
&lt;p&gt;Next, let&amp;rsquo;s build this into our duplicity-backup script (basic configuration &lt;a href=&#34;../duplicity_backup_script&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Building on top of this configuration, we now simply change the &lt;code&gt;DEST&lt;/code&gt; variable to the configuration used in the above command.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DEST=&amp;#39;&amp;#34;multi:///home/matt/multiconfig.conf?mode=mirror&amp;amp;onfail=abort&amp;#34;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Please notice the odd quoting - as this file will be sourced by the backup-script, we need to wrap the command we want to pass to duplicity in single-quotes - so the double-quoted string is then passed on to duplicity (with the quotes).
Let&amp;rsquo;s run duplicity-backup.sh and see if our configuration does indeed work&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --full
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, check both local and remote sftp folder. You should have another full backup file there, in addition to the one we had before.&lt;/p&gt;
&lt;p&gt;We can also set this up for other backends like &lt;a href=&#34;../dupicity-backup-dropbox&#34;&gt;dropbox&lt;/a&gt;, simply pass in the environment variable we had to configure in the dropbox post &lt;code&gt;DPBX_ACCESS_TOKEN&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Local disk test&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file:///home/matt/backupmulti&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backup to dropbox&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dpbx:///duplicitytest1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;env&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DPBX_ACCESS_TOKEN&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;teBo-PD8bsUAA&amp;lt;redacted&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that this will work for other backends like &lt;a href=&#34;../duplicity-onedrive/&#34;&gt;Onedrive&lt;/a&gt;, &lt;a href=&#34;../duplicity-hubic&#34;&gt;Hubic&lt;/a&gt; or &lt;a href=&#34;../duplicity-google-drive&#34;&gt;Google drive&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;Run the backup-script again.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --full
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Check your dropbox-folder - you should now have a new full backup in that folder.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In the &lt;a href=&#34;../duplicity_getting_started&#34;&gt;first post&lt;/a&gt; of this series, I highlighted the backup-strategy everyone who cares about his data should use.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A basic rule for Backups is the 3-2-1 rule: &lt;strong&gt;3&lt;/strong&gt; total copies of the data - on &lt;strong&gt;2&lt;/strong&gt; different mediums, at least &lt;strong&gt;1&lt;/strong&gt; offsite.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This part has now accomplished exactly that by having&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 copies of the data:
&lt;ol&gt;
&lt;li&gt;original version&lt;/li&gt;
&lt;li&gt;local backup&lt;/li&gt;
&lt;li&gt;remote backup&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;2 different mediums
&lt;ol&gt;
&lt;li&gt;local system&lt;/li&gt;
&lt;li&gt;remote system&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;1 offsite
&lt;ol&gt;
&lt;li&gt;remote backup in the cloud (or on a different system using sftp)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could even go further, and configure multiple (or all) Cloud services at once, and have more than 3 copies of the data - but that is overkill most of the time, but will of course depend on the importance of the data.&lt;/p&gt;
&lt;p&gt;This post will conclude the duplicity series for now.
We have now successfully &lt;a href=&#34;../duplicity_getting_started&#34;&gt;setup duplicity&lt;/a&gt;, &lt;a href=&#34;../duplicity_remote&#34;&gt;syncronized&lt;/a&gt; &lt;a href=&#34;../duplicity-onedrive&#34;&gt;to&lt;/a&gt;  &lt;a href=&#34;../duplicity-hubic&#34;&gt;various&lt;/a&gt; &lt;a href=&#34;../duplicity-google-drive&#34;&gt;remote&lt;/a&gt; &lt;a href=&#34;../dupicity-backup-dropbox&#34;&gt;sites&lt;/a&gt;, &lt;a href=&#34;../duplicity-backup-email-notifications&#34;&gt;setup&lt;/a&gt; &lt;a href=&#34;../duplicity-backup-ifttt-notifications&#34;&gt;notifications&lt;/a&gt;, and syncronized to multiple sites at once in this post.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - going cloud</title>
      <link>https://blog.xmatthias.com/post/duplicity-backup-going-cloud/</link>
      <pubDate>Sat, 17 Feb 2018 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-backup-going-cloud/</guid>
      
      <description>&lt;p&gt;In the upcomming parts, we will configure the duplicity-backup.sh script for different cloud services. Also, we will be using the &amp;ldquo;multi&amp;rdquo;-plugin to setup backups to multiple different servers.
Personally, i would never backup to a cloud-server unencrypted - so duplicity helps by encrypting locally before uploading to the different cloud services.&lt;/p&gt;
&lt;p&gt;I will split the posts per cloud service, so there is some order (most people will probably be interrested in only a few services).
There will be one part per cloud service to keep some order.
I will update this post with links to the &amp;ldquo;duplicity cloud service&amp;rdquo; posts.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&#34;../duplicity_getting_started&#34;&gt;first part&lt;/a&gt;, we setup our GPG keys to encrypt backups. In the &lt;a href=&#34;../duplicity_remote&#34;&gt;second part&lt;/a&gt;, we looked at remote backups using sftp, scheduling and wrote a quick script for the backup.
The &lt;a href=&#34;../duplicity_backup_script&#34;&gt;third part&lt;/a&gt; covered an &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;open source script&lt;/a&gt;, which made setting up different options very easy as it has an example configuration which only requires minor modifications.&lt;/p&gt;
&lt;h3 id=&#34;posts-in-this-series&#34;&gt;Posts in this series&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity_getting_started&#34;&gt;Duplicity backup - getting started&lt;/a&gt; &amp;ndash; &lt;em&gt;Setup GPG Keys for encrypted backups&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity_remote&#34;&gt;Backup to remote sites&lt;/a&gt; &amp;ndash; &lt;em&gt;First backups to remote sites&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity_backup_script&#34;&gt;duplicity backup script&lt;/a&gt; &amp;ndash; &lt;em&gt;Using &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity-backup.sh&lt;/a&gt; to simplify backups with duplicity&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity-onedrive&#34;&gt;Microsoft Onedrive&lt;/a&gt; &amp;ndash; &lt;em&gt;Backup to Microsoft Onedrive&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity-hubic&#34;&gt;hubic&lt;/a&gt; &amp;ndash; &lt;em&gt;Backup to hubic.com&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity-google-drive&#34;&gt;Google Drive&lt;/a&gt; &amp;ndash; &lt;em&gt;Backup to Google Drive&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity-backup-email-notifications&#34;&gt;Email Notifications&lt;/a&gt; &amp;ndash; &lt;em&gt;Get notified in case of problems&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity-backup-ifttt-notifications&#34;&gt;IFTTT notifications&lt;/a&gt; &amp;ndash; &lt;em&gt;Another notification method&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../dupicity-backup-dropbox&#34;&gt;Dropbox&lt;/a&gt; &amp;ndash; &lt;em&gt;Backup to Dropbox&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../duplicity-multisite-backup&#34;&gt;multi&lt;/a&gt; &amp;ndash; &lt;em&gt;Backup to multiple sites&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;This post is regularily updated once new parts in this series are posted.&lt;/em&gt;&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>dupicity backup - Dropbox</title>
      <link>https://blog.xmatthias.com/post/dupicity-backup-dropbox/</link>
      <pubDate>Sat, 03 Feb 2018 20:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/dupicity-backup-dropbox/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I would recommend to first read the &lt;a href=&#34;../duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;../duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post, but is required for the tutorial to work).
You should also have a look at the &lt;a href=&#34;../duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains a list of all posts in this series.
The basic configuration from &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used as basis in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;dropbox&#34;&gt;Dropbox&lt;/h2&gt;
&lt;p&gt;First of all, we obviously need a private &lt;a href=&#34;https://www.dropbox.com/referrals/AAC-EBewLciunyCRoKfSU3le1_16V2jiHnk&#34;&gt;Dropbox&lt;/a&gt; (&lt;em&gt;Full disclosure:&lt;/em&gt; Referral link - non-referral link &lt;a href=&#34;https://www.dropbox.com&#34;&gt;here&lt;/a&gt;) account. The free version currently offers 2 GB free storage, which however can be extended by inviting new people and completing some tasks. Mainly in the past, many were able to get ton of free storage from multiple different actions by Dropbox.&lt;/p&gt;
&lt;p&gt;The dropbox-backend does require the &lt;em&gt;dropbox python SDK&lt;/em&gt;, which we will install using the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install dropbox&lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt;6.9.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Note: version 6.9.0 or below is required, as version 7.1 introduced some breaking changes, which will result in error-messages saying something like &lt;code&gt;TypeError: expected request_binary as binary type, got &amp;lt;type &#39;file&#39;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next, let&amp;rsquo;s log into &lt;a href=&#34;https://www.dropbox.com&#34;&gt;Dropbox&lt;/a&gt; and go to the &lt;a href=&#34;https://www.dropbox.com/developers/apps/create&#34;&gt;developer tools&lt;/a&gt; to create a new &amp;ldquo;Dropbox API&amp;rdquo; Application.
We will use an &amp;ldquo;App folder&amp;rdquo; application here, which limits access to one folder of Dropbox instead of the whole Dropbox and name the application &amp;ldquo;duplicity_sync_xmatthias&amp;rdquo;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note:  The Application name must be unique accross all Dropbox applications, because in theory the application could be published (which we will not do).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&#34;dropbox1_cut.png&#34; alt=&#34;dropbox1_cut&#34;&gt;&lt;/p&gt;
&lt;p&gt;Click on &lt;em&gt;Create App&lt;/em&gt; to complete the application creation.
In the next screen, we can see that the application is in &amp;ldquo;development&amp;rdquo; status. All this means is that it is not published (which don&amp;rsquo;t intend to do) and only this user (and invited test-users) are allowed to use this API key.&lt;/p&gt;
&lt;p&gt;According to the &lt;a href=&#34;https://duplicity.nongnu.org/duplicity.1.html#sect12&#34;&gt;duplicty documentation&lt;/a&gt;, we now have 2 options - generate the API key on this site - or supply duplicity with the variables &lt;code&gt;DPBX_APP_KEY&lt;/code&gt; and &lt;code&gt;DPBX_APP_SECRET&lt;/code&gt; and have duplicity run through the OAuth workflow.
As everyone creates his own &amp;ldquo;Application&amp;rdquo; in Dropbox, there is no benefit to this approach (this would only be viable if you share the application with someone else) - therefore we generate the Access Token in this window.
Generate the Access Token as shown in the picture below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;dropbox2_cut.png&#34; alt=&#34;dropbox2_cut&#34;&gt;&lt;/p&gt;
&lt;p&gt;Copy the string which will appear instead of the Button and use it as variable &lt;code&gt;DPBX_ACCESS_TOKEN&lt;/code&gt;. (Mine is redacted as it would grant access to my Dropbox).
Then, run the command we know from previous Posts to test connectivity with Dropbox.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export DPBX_ACCESS_TOKEN&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;teBo-PD8bsUAA&amp;lt;redacted&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB  /tmp/backupTest/ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dpbx:///duplicitytest1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When first running this command, you may encounter an error similar to mine:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB  /home/matt/test/ dpbx:///duplictytest2
Exception [ApiError(&amp;#39;87ed601063102a7aa75f9e400f9e718e&amp;#39;, ListFolderError(u&amp;#39;path&amp;#39;, LookupError(u&amp;#39;not_found&amp;#39;, None)))]:
| Traceback (most recent call last):
|   File &amp;#34;/usr/lib/python2.7/dist-packages/duplicity/backends/dpbxbackend.py&amp;#34;, line 76, in wrapper
|     return f(self, *args)
|   File &amp;#34;/usr/lib/python2.7/dist-packages/duplicity/backends/dpbxbackend.py&amp;#34;, line 384, in _list
|     resp = self.api_client.files_list_folder(remote_dir)
|   File &amp;#34;/home/matt/.local/lib/python2.7/site-packages/dropbox/base.py&amp;#34;, line 673, in files_list_folder
|     None,
|   File &amp;#34;/home/matt/.local/lib/python2.7/site-packages/dropbox/dropbox.py&amp;#34;, line 272, in request
|     user_message_locale)
| ApiError: ApiError(&amp;#39;87ed601064102f7da75f9e400f9e718e&amp;#39;, ListFolderError(u&amp;#39;path&amp;#39;, LookupError(u&amp;#39;not_found&amp;#39;, None)))
Attempt 1 failed. BackendException: dpbx api error &amp;#34;ApiError(&amp;#39;87ed601063102a7aa75f9e400f9e718e&amp;#39;, ListFolderError(u&amp;#39;path&amp;#39;, LookupError(u&amp;#39;not_found&amp;#39;, None)))&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The duplicity documentation states that the folder needs to exist. Let&amp;rsquo;s suffice this requirement by going to our Dropbox home, navigate to &amp;ldquo;Apps/&amp;lt;your_app_name&amp;gt;&amp;rdquo; and create the folder. In my case, the url to this is &lt;code&gt;https://www.dropbox.com/home/Apps/duplicity_sync_xmatthias&lt;/code&gt; - but your&amp;rsquo;s will differ depending on the selected name for your &amp;ldquo;application&amp;rdquo;.
You can also use subfolders if multiple separate backups are required in the same account.
Please note that Dropbox will sync the encrypted backup to all connected PC&amp;rsquo;s by default (unselect from &amp;ldquo;selective sync&amp;rdquo; if this is not desired).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;dropbox3_cut.png&#34; alt=&#34;dropbox3_cut&#34;&gt;&lt;/p&gt;
&lt;p&gt;Create the folder you&amp;rsquo;d like to use (in my case, &lt;code&gt;duplicitytest1&lt;/code&gt;) and rerun the above command.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export DPBX_ACCESS_TOKEN&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;teBo-PD8bsUAA&amp;lt;redacted&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB  /tmp/backupTest/ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dpbx:///duplicitytest1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Duplicity will now backup and upload the data.&lt;/p&gt;
&lt;h2 id=&#34;duplicity-backupsh&#34;&gt;duplicity-backup.sh&lt;/h2&gt;
&lt;p&gt;To add this to the &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity-backup.sh&lt;/a&gt; script we used &lt;a href=&#34;../duplicity_backup_script&#34;&gt;previously&lt;/a&gt;, change &lt;code&gt;DEST&lt;/code&gt; to the following and add the access-token as &lt;code&gt;DPBX_ACCESS_TOKEN&lt;/code&gt; to the script:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DPBX_ACCESS_TOKEN=&amp;#34;teBo-PD8bsUAA&amp;lt;redacted&amp;gt;&amp;#34;
DEST=&amp;#34;dpbx:///duplicitytest1&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The rest of the configuration remains identical to the configuration used in the &lt;a href=&#34;../duplicity_backup_script&#34;&gt;duplicity-backup.sh post&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTE: should you receive the error &lt;code&gt;BackendException: dpbx: DPBX_APP_KEY environment variable not set&lt;/code&gt; while running the above script, please update duplicity-backup.sh by issuing a &lt;code&gt;git pull&lt;/code&gt; as the Dropbox-functionality required a pull-request to fully work. Also, make sure that you use the &lt;code&gt;dev&lt;/code&gt; branch, as the PR has so far only been applied there. Previously, the access token has not been exported correctly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We now run the duplicity-backup.sh script.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --backup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A incremental backup should appear in your Dropbox folder.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;dropbox4_cut.png&#34; alt=&#34;dropbox4_cut&#34;&gt;&lt;/p&gt;
&lt;p&gt;You may want to now schedule the backup using the cron job as shown in the &lt;a href=&#34;../duplicity_backup_script&#34;&gt;post&lt;/a&gt; presenting duplicity-backup.sh.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Everyone prefers a different cloud-storage provider. All offer different possibilities at different prices and with different advantages / disadvantages. I don&amp;rsquo;t want to judge which one others should use, and have therefore shown the setup &lt;a href=&#34;../duplicity-hubic&#34;&gt;for&lt;/a&gt; &lt;a href=&#34;../duplicity-google-drive&#34;&gt;multiple&lt;/a&gt; &lt;a href=&#34;../duplicity-onedrive&#34;&gt;services&lt;/a&gt;.
Dropbox presents a good choice from a security point of view by allowing to only expose a dedicated App-folder to duplicity  (we&amp;rsquo;ve seen this &lt;a href=&#34;../duplicity-onedrive/#drawbacks&#34;&gt;differently from onedrive&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In the end, it does not matter which provider is used, as long as the backup is executed regularly, tested and implemented following the &amp;ldquo;3-2-1&amp;rdquo; rule:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;3 total copies of the data - on 2 different mediums, at least 1 off site.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&#34;full-disclosure&#34;&gt;Full disclosure&lt;/h4&gt;
&lt;p&gt;If you register with Dropbox using the link above, I will get free space added through the referral program. If you want to avoid this, please use &lt;a href=&#34;https://www.dropbox.com&#34;&gt;this&lt;/a&gt; link or type in &lt;a href=&#34;https://www.dropbox.com&#34;&gt;https://www.dropbox.com&lt;/a&gt; into your browser manually.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>XPS 13 9360R Audio problems</title>
      <link>https://blog.xmatthias.com/post/xps-13-audio/</link>
      <pubDate>Mon, 22 Jan 2018 21:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/xps-13-audio/</guid>
      
      <description>&lt;h3 id=&#34;bluetooth-headset&#34;&gt;Bluetooth headset&lt;/h3&gt;
&lt;p&gt;While setting up my &lt;a href=&#34;../new-notebook/&#34;&gt;new notebook&lt;/a&gt;, I discovered that my bluetooth headset would not work after suspend to RAM.
It works perfectly fine when cold-booting (or restarting) - however after resume I struggled to get it to work without restarting the bluetooth service (or pulseaudio).&lt;/p&gt;
&lt;p&gt;I did a lot of research around this area, suspecting the default configurations of either pulseaudio or bluez to be at fault, however none of the &amp;ldquo;ultimate guides for bluetooth headsets in linux&amp;rdquo; I found online did work. I also could not rule out the headset (&lt;a href=&#34;https://www.bragi.com/thedash/&#34;&gt;The Dash&lt;/a&gt;), which has a certain age and is not without flaws.&lt;/p&gt;
&lt;p&gt;The headset would connect, but then would immediately disconnect (or connect and not be recognized as Audio device).
The log would show the following errors&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Jan 18 22:30:57 xps pulseaudio[3293]: E: [pulseaudio] backend-native.c: Device doesnt exist for /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX
Jan 18 22:30:57 xps bluetoothd[2185]: Headset Voice gateway replied with an error: org.bluez.Error.InvalidArguments, Unable to handle n
Jan 18 22:31:03 xps bluetoothd[2185]: Discover: Connection timed out (110)
Jan 18 22:31:11 xps bluetoothd[2185]: Discover: Connection timed out (110)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After searching for quite some time (a few hours), I ran into &lt;a href=&#34;https://bugzilla.redhat.com/show_bug.cgi?id=1534857&#34;&gt;this&lt;/a&gt; bugreport in Red Hat&amp;rsquo;s bug tracker, which seemed to somehow match my problem.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t search for problematic updates as the laptop is brand-new and the headset never worked flawlessly, but looking back (and knowing the solution) it does make sense.
After downloading the package from &lt;a href=&#34;https://archive.archlinux.org/packages/b/bluez/&#34;&gt;archive.archlinux.org&lt;/a&gt; and downgrading bluez from &lt;code&gt;bluez-5.48-1&lt;/code&gt; to &lt;code&gt;bluez-5.47-2&lt;/code&gt; the headset connected immediately. I then added the package to &lt;code&gt;/etc/pacman.conf&lt;/code&gt; under &lt;code&gt;IgnorePkg&lt;/code&gt; so regular updates are not affected.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be monitoring the bug-report for changes, hoping for a soonish fix in bluez.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; The new release (bluez-5.48-2) fixed the problem according to the bug-report. I installed it on my system, and indeed, the problem is now gone.&lt;/p&gt;
&lt;h3 id=&#34;wired-headset&#34;&gt;Wired headset&lt;/h3&gt;
&lt;p&gt;After fixing my bluetooth headset (which i use most of the days), I also tried my wired headset (while recharging the bluetooth headset) only to discover that there was a constant background noise (hissing, crackling, &amp;hellip;).
Again, the problem only manifested itself after Suspend or hibernate, but not when restarting / cold booting.&lt;/p&gt;
&lt;p&gt;I could not get to the bottom of this problem yet (I will update this post should i ever find a permanent solution) - but for now I am not 100% sure what the problem is.
What i know is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the noise is only present after resume&lt;/li&gt;
&lt;li&gt;the noise is only present in devices connected via 3.5mm Jack&lt;/li&gt;
&lt;li&gt;the noise is gone if i reload the kernel-module snd_hda_intel&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Changing the power-related settings of the module did not help (with power-saving turned off, the problem still appears after every resume).&lt;/p&gt;
&lt;p&gt;The only solution i found so far is to reload the kernel-module (for now manually, whenever i need it) using the following script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#fix pulseaudio headset crackling&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl --user stop pulseaudio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo rmmod snd_hda_intel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo modprobe snd_hda_intel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl --user start pulseaudio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pulseaudio restarted&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script stops &lt;a href=&#34;https://wiki.archlinux.org/index.php/PulseAudio&#34;&gt;pulseaudio&lt;/a&gt;, removes and reloads the module, and starts pulseaudio again.
It produces a fairly loud crack in the headset, and afterwards i need to unplug/replug my headset so it is set as default source, however at least i don&amp;rsquo;t have to reboot whenever i want my headset to work.&lt;/p&gt;
&lt;p&gt;I have not given up on a permanent solution, but this is something that does not bother me too much short-term and i don&amp;rsquo;t currently want to invest too much time.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>New Notebook</title>
      <link>https://blog.xmatthias.com/post/new-notebook/new-notebook/</link>
      <pubDate>Sat, 20 Jan 2018 20:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/new-notebook/new-notebook/</guid>
      
      <description>&lt;p&gt;I recently decided that after 3 years with my current Notebook, it&amp;rsquo;s time to get a new one. (No, not one like in the image above)
&lt;em&gt;NB: The decision-criteria are based from around Christmas 2017, so newly announced Laptops on the CES have not been considered.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My criteria where as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;14&amp;rsquo;&amp;rsquo; or smaller&lt;/li&gt;
&lt;li&gt;Ultrabook-style (1.6 kg or lower)&lt;/li&gt;
&lt;li&gt;decent (8+) hour battery life&lt;/li&gt;
&lt;li&gt;out of the box Linux support for most components&lt;/li&gt;
&lt;li&gt;8th generation Intel CPU i5 or i7  &lt;em&gt;(this has proven to be the most complicated&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;16 G of Ram&lt;/li&gt;
&lt;li&gt;Matte Display, non-Touch&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;competitors-and-quick-details&#34;&gt;Competitors and quick details&lt;/h3&gt;
&lt;p&gt;For a long time, I had the following candidates on my list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lenovo X1 Carbon 2017&lt;/li&gt;
&lt;li&gt;Asus Zenbook UX3430UA-GV376T&lt;/li&gt;
&lt;li&gt;Dell XPS13 9360R&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;lenovo-x1-carbon-2017&#34;&gt;Lenovo X1 Carbon 2017&lt;/h4&gt;
&lt;p&gt;Lenovo did disqualify as it did not have the 8th Gen CPU announced yet. They did &lt;a href=&#34;https://www.theverge.com/2017/1/3/14142392/new-lenovo-thinkpad-x1-carbon-laptop-announced-price-ces-2017&#34;&gt;announce&lt;/a&gt; this refresh at CES 2018 - however too late for me. While i did expect this announcement, I had other reasons to go with what i got (you&amp;rsquo;ll see below why).&lt;/p&gt;
&lt;h4 id=&#34;asus-zenbook-ux3430ua-gv376t&#34;&gt;Asus Zenbook UX3430UA-GV376T&lt;/h4&gt;
&lt;p&gt;Asus has the UX3430UA (Matte Display, 14&amp;rsquo;&amp;rsquo; Display in the body of the 13&amp;rsquo;&amp;rsquo; UX330UA, i7-8550U, 16G Ram). While this looks like a great Laptop, most concerns where with Linux support as well as Coil Whine (not on all Devices apparently, so it&amp;rsquo;s like playing Lottery).
The exterior of Zenbooks looks great, however is a fingerprint magnet according to many Reviews of earlier models. As the Case did not really change, this is to be expected from this device.
Also, this model was brandnew in December, so not many reviews were available at that time.&lt;/p&gt;
&lt;h4 id=&#34;dell-xps13-9360r&#34;&gt;Dell XPS13 9360R&lt;/h4&gt;
&lt;p&gt;I always wanted a XPS 13 since they first announced at CES 2012. However, early models only had very slow CPU&amp;rsquo;s so they were no option last time around.
However, this has changed greatly. With Intel&amp;rsquo;s release of the Kaby Lake Refresh CPU&amp;rsquo;s (4 cores in Ultrabook CPU&amp;rsquo;s), this seemed like the best bet.
The only other competitor with an 8thgen CPU and Matte Screen the XPS 13 had in December the Asus Zenbook mentioned above, all other competitors have either a older CPU model (Lenovo X1 Carbon) or a glossy screen (Swift 3, Lenovo Yoga, Huawei X).
I did not jump to this Laptop because I already liked the 2012 version (other Manufacturers have nice Laptops too), but thought and researched for about a Month before proceeding with the purchase.&lt;/p&gt;
&lt;h3 id=&#34;decision&#34;&gt;Decision&lt;/h3&gt;
&lt;p&gt;Knowing that Lenovo would (probably) announce a refreshed version of the X1 Carbon at CES 2018, all 3 had equal chances.
Both the Zenbook and the XPS ranged in approximately the same price range (including shipping, with the specs i wanted), however the X1 Carbon (in my desired configuration) would have been ~200$ more expensive. Expecting the refresh in a similar price-range, i was one step closer to taking a decision.&lt;/p&gt;
&lt;p&gt;Mid to end-December, the first reviews of Zenbooks with 8th Gen CPU&amp;rsquo;s appeared. These are important as they showed that battery-life dropped by ~half to the older CPU. Looking at similar &lt;a href=&#34;https://www.notebookcheck.net/Dell-XPS-13-9360R-i5-8250U-QHD-Laptop-Review.266690.0.html&#34;&gt;reviews&lt;/a&gt; about the XPS, these only mention a ~15% drop on battery life compared to the previous model.
Charging of the XPS 13 is possible using both the included charger or a USB-C charger (Though only special Charger models which have enough power output). I did not find a clear indication if this is also possible for the Zenbook (which did also influence my decision - as it might mean one fewer charger when traveling).
Also, having a 60W Battery compared to a 50W Battery in the Zenbook helped the decision.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I took the Dell XPS 13 9360R (Refreshed with 8th gen Intel CPU)&lt;/strong&gt;
I think my decision was thoroughly researched based on choosing the longer lasting, more linux-proven Notebook (Dell does offer a Developer-edition with Ubuntu for of most XPS models).&lt;/p&gt;
&lt;h3 id=&#34;closing&#34;&gt;Closing&lt;/h3&gt;
&lt;p&gt;I received the XPS 13 a week ago, first thing i did was setting up Arch-Linux (my distribution of choice). Almost everything worked out of the box with only few problems (some of which will deserve their own Blog-post).&lt;/p&gt;
&lt;p&gt;Dell announced a refreshed version of the Dell XPS 13 (&lt;a href=&#34;https://www.theverge.com/circuitbreaker/2017/10/6/16434992/dell-xps-13-model-ces-2018-ultrabook&#34;&gt;the Verge&lt;/a&gt;) with some improvements (smaller Case, different colors, different location for the Webcam). However - i don&amp;rsquo;t expect to be using the Webcam at all - and the new version (Model 9370) only has a 50W Battery, which will reduce the runtime by some.&lt;/p&gt;
&lt;p&gt;So far, I did not regret my decision even though a new Model (9370) was announced before i received my Notebook.
The Dell XPS 13 was an affordable (even though not cheap) decision and is running smoothly, silently, and (so far) reliably.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Why applying https everywhere is important</title>
      <link>https://blog.xmatthias.com/post/why-https-everywhere-is-important/</link>
      <pubDate>Wed, 27 Dec 2017 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/why-https-everywhere-is-important/</guid>
      
      <description>&lt;p&gt;Until recently, I did not realize that https is important for &lt;strong&gt;ALL&lt;/strong&gt; sites, not just for sites containing sensitive information, login pages, banking websites, shopping pages pages. The eye-opener for me was &lt;a href=&#34;https://www.troyhunt.com/im-sorry-you-feel-this-way-natwest-but-https-on-your-landing-page-is-important/&#34;&gt;Troy Hunts article&lt;/a&gt;  about this same topic. Troy talks about a Bank having their landing-page http only - while forwarding to https for the login.
The problem Troy points out is that the link to the secure login-page can be intercepted / modified / redirected to any other site by anyone able to MitM your connection (ISP, Coffee shop, malicious actor on open Wifi, VPN Provider, &amp;hellip;).&lt;/p&gt;
&lt;p&gt;While https will not fully solve this (things like ssl strip can still be applied but can be spotted fairly easy), it does increase the complexity for the (malicious) actor to redirect you to the wrong site.&lt;/p&gt;
&lt;h3 id=&#34;closing&#34;&gt;Closing&lt;/h3&gt;
&lt;p&gt;Honestly, I completely agree with Troy&amp;rsquo;s post. I did not realize the importance (other than for privacy protection) before his post, but it was eye-opening to me and showed me that https has to be applied everywhere to be effective.&lt;/p&gt;
&lt;p&gt;People, apply https &lt;strong&gt;everywhere&lt;/strong&gt; - with &lt;a href=&#34;https://letsencrypt.org&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; it does not cost a penny and is easy to configure for almost every server setup.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - email notifications</title>
      <link>https://blog.xmatthias.com/post/duplicity-backup-email-notifications/</link>
      <pubDate>Sat, 02 Dec 2017 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-backup-email-notifications/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I recommend to first read the &lt;a href=&#34;../duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;../duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post).
You should also visit the &lt;a href=&#34;../duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains a list of all posts in this series.
The basic configuration of &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;email-notifications&#34;&gt;Email notifications&lt;/h2&gt;
&lt;p&gt;When relying on a backup system it is important to be confident that everything worked. The easiest solution to accomplish this is by testing your backup on a regular basis, and by getting notified if something goes astray.
The &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity backup script&lt;/a&gt; does offer several notification methods for notifications, email, Slack, pushover, &lt;a href=&#34;https://ifttt.com/&#34;&gt;IFTTT&lt;/a&gt; and Telegram.&lt;/p&gt;
&lt;p&gt;This post will focus on email notification setup as almost everyone uses email, whereas other services have a more specific target audience.&lt;/p&gt;
&lt;p&gt;Setup is similar for each of the notification services - simply filling in the variables in the configuration example for the service you&amp;rsquo;d like to use.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: While this covers E-mail notifications, I would recommend to rely on &lt;a href=&#34;https://ifttt.com/&#34;&gt;IFTTT&lt;/a&gt; for notifications - the setup is simpler than for email as explained in &lt;a href=&#34;../duplicity-backup-ifttt-notifications&#34;&gt;this post&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;email-configuration&#34;&gt;Email configuration&lt;/h3&gt;
&lt;p&gt;To have a working email notification, we first need to configure our system to be able to send emails. On Debian, the default is exim4.
If you already have your system configured to send emails, then you can skip to the next section, otherwise read on - it won&amp;rsquo;t take long.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start by reconfiguring exim4&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo dpkg-reconfigure exim4-config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The setup will guide us through the configuration. We will only configure outgoing emails and have the server listen on localhost only.&lt;/p&gt;
&lt;p&gt;The only 3 settings we need to change are &amp;ldquo;General type of mail configuration: &amp;quot; to &amp;ldquo;internet site; mail is sent and received directly using SMTP&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_email1.png&#34; alt=&#34;duplicity_email1&#34;&gt;&lt;/p&gt;
&lt;p&gt;, &amp;ldquo;System mail name: &amp;quot; to your domain name and&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_email2.png&#34; alt=&#34;duplicity_email2&#34;&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;IP-addresses to listen on for incoming SMTP connections:&amp;rdquo; to 127.0.0.1 to make sure the SMTP server is only listening on localhost. Otherwise, we would have an open SMTP server, and it would not take long until it is abused to send Spam emails.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_email3.png&#34; alt=&#34;duplicity_email3&#34;&gt;&lt;/p&gt;
&lt;p&gt;All other settings can remain at default assuming you did not already configure this previously.&lt;/p&gt;
&lt;p&gt;Now, we can run a test by sending an email to our email address:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test Email&amp;#34;&lt;/span&gt; | mailx -s &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test email 1&amp;#34;&lt;/span&gt; youremail@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Check your mailbox (also the Spam folder) for an email with &amp;ldquo;test email 1&amp;rdquo; as subject. You should receive it within minutes if everything is working correctly.&lt;/p&gt;
&lt;h3 id=&#34;script-configuration&#34;&gt;Script configuration&lt;/h3&gt;
&lt;p&gt;Open the configuration we created in &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; and search for EMAIL.
Change the following settings to your preference (your email address, and a custom subject if you&amp;rsquo;d like to change it from the default &lt;code&gt;duplicity-backup Alert ${LOG_FILE}&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;EMAIL_TO=youremail@gmail.com
EMAIL_FROM=duplicity@yourdomain.com
EMAIL_SUBJECT=
#EMAIL_FAILURE_ONLY=&amp;#34;yes&amp;#34; # send e-mail only if there was an error while creating backup
EMAIL_FAILURE_ONLY=&amp;#34;no&amp;#34; # always send emails
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I changed the setting &lt;strong&gt;EMAIL_FAILURE_ONLY&lt;/strong&gt; to always send me an email (so i am sure the backup ran). This is also useful to test the settings - if the first email would be sent when the backup fails we cannot be sure sending mails actually works as we never tested it.&lt;/p&gt;
&lt;p&gt;Now, run the script again and check your mailbox afterwards.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --backup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script output should end with &amp;ldquo;Email notification sent to &lt;a href=&#34;mailto:youremail@gmail.com&#34;&gt;youremail@gmail.com&lt;/a&gt; using mailx&amp;rdquo;
If the configuration was correct, you should have received an email. Don&amp;rsquo;t forget to check the Spam-folder - depending on the email provider the email may be detected as Spam (we did not set the server up to deliver safe, verified emails - so the authenticity of the email is not guaranteed - as the sender address is known (configured above) we can whitelist to get the emails regularly).&lt;/p&gt;
&lt;p&gt;No matter what notification you configure - configure at least one of them so you are aware that the backup failed and needs manual interaction / checking.&lt;/p&gt;
&lt;p&gt;The best backup-strategy is worthless if it fails to backup silently or the backup is never tested, so please use either this or the &lt;a href=&#34;../duplicity-backup-ifttt-notifications&#34;&gt;other&lt;/a&gt; method to get notified of problems with the backup.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - IFTTT notifications</title>
      <link>https://blog.xmatthias.com/post/duplicity-backup-ifttt-notifications/</link>
      <pubDate>Sat, 02 Dec 2017 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-backup-ifttt-notifications/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I recommend to first read the &lt;a href=&#34;../duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;../duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post).
You should also visit the &lt;a href=&#34;../duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains a list of all posts in this series.
The basic configuration of &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When relying on a backup system it is important to be confident that everything worked. The easiest solution to accomplish this is by testing your backup on a regular basis, and by getting notified if something goes astray.
The &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity backup script&lt;/a&gt; does offer several notification methods for notifications, email, Slack, pushover, &lt;a href=&#34;https://ifttt.com/&#34;&gt;IFTTT&lt;/a&gt; and Telegram.
In this post, we will see how to setup &lt;a href=&#34;https://ifttt.com/&#34;&gt;IFTTT&lt;/a&gt; notifications for duplicity.&lt;/p&gt;
&lt;h2 id=&#34;ifttt-notifications&#34;&gt;IFTTT notifications&lt;/h2&gt;
&lt;p&gt;In order to use &lt;a href=&#34;https://ifttt.com&#34;&gt;IFTTT&lt;/a&gt; you&amp;rsquo;ll need an account on the site. If you don&amp;rsquo;t have one, please register yourself with the service to continue with the tutorial.
Go to &lt;a href=&#34;https://ifttt.com/my_applets&#34;&gt;My applets&lt;/a&gt; and click on &amp;ldquo;New Applet&amp;rdquo; (or use &lt;a href=&#34;https://ifttt.com/create&#34;&gt;this&lt;/a&gt; link to get to this page directly).
Click on the &lt;em&gt;This&lt;/em&gt; link, search for &amp;ldquo;webhooks&amp;rdquo; and select it.
&lt;img src=&#34;duplicity_ifttt1.png&#34; alt=&#34;duplicity_ifttt1&#34;&gt;
Click on Receive a web request.&lt;/p&gt;
&lt;p&gt;Insert an &lt;em&gt;event name&lt;/em&gt; (keep note of it - we&amp;rsquo;ll need this again later) and click on &lt;em&gt;Create Trigger&lt;/em&gt;.
&lt;img src=&#34;duplicity_ifttt2.png&#34; alt=&#34;duplicity_ifttt2&#34;&gt;&lt;/p&gt;
&lt;p&gt;Click on &lt;em&gt;That&lt;/em&gt; and select a service you&amp;rsquo;d like to Trigger.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using &lt;em&gt;Send me an email&lt;/em&gt; in this case, but feel free to experiment with other notification methods.
&lt;img src=&#34;duplicity_ifttt3.png&#34; alt=&#34;duplicity_ifttt3&#34;&gt;
Click on &amp;ldquo;Send me an email&amp;rdquo;. For now, keep all fields identical - you can change the template later if you wish to receive a different subject or content.
&lt;img src=&#34;duplicity_ifttt4.png&#34; alt=&#34;duplicity_ifttt4&#34;&gt;
Confirm the template by clicking on &lt;em&gt;create action&lt;/em&gt;, then review and confirm the applet by clicking on &lt;em&gt;Finish&lt;/em&gt; in the next screen.&lt;/p&gt;
&lt;h2 id=&#34;duplicity-backupsh&#34;&gt;duplicity-backup.sh&lt;/h2&gt;
&lt;p&gt;Implementing this into the &lt;code&gt;duplicity-backup.sh&lt;/code&gt; script requires the configuration from the &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;duplicity-backup.sh post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Scroll all the way down (or search for &amp;ldquo;IFTTT&amp;rdquo;).&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Provider: IFTTT
IFTTT_KEY=&amp;#34;&amp;#34; # Key for MAKER channel at IFTTT
IFTTT_MAKER_EVENT=&amp;#34;duplicity&amp;#34; # name the event to trigger at IFTTT Maker Channel
IFTTT_HOOK_URL=&amp;#34;https://maker.ifttt.com/trigger/$IFTTT_MAKER_EVENT/with/key/$IFTTT_KEY&amp;#34; # ONLY change this if IFTTT changes it
IFTTT_VALUE2=&amp;#34;&amp;#34; # general purpose value to pass to your maker channel (optional)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The settings we are interested in are &lt;code&gt;IFTTT_KEY&lt;/code&gt; and &lt;code&gt;IFTTT_MAKER_EVENT&lt;/code&gt; (and eventually &lt;code&gt;IFTTT_VALUE2&lt;/code&gt; - we can use this to tell us the name of the backup job).
IFTTT_MAKER_EVENT will be set to the &lt;em&gt;event name&lt;/em&gt; we configured on IFTTT earlier.
Next, go to &lt;a href=&#34;https://ifttt.com/services/maker_webhooks/settings&#34;&gt;IFTTT Webhook settings&lt;/a&gt; to get value for the  &lt;code&gt;IFTTT_KEY&lt;/code&gt;. You&amp;rsquo;ll see an URL - the last part of the URL  &lt;a href=&#34;https://maker.ifttt.com/use/&#34;&gt;https://maker.ifttt.com/use/&lt;/a&gt;&lt;strong&gt;c734bdvJ5afSlnwVRukZZ2&lt;/strong&gt; (in bolt) is your key and goes to the &lt;code&gt;IFTTT_KEY&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;Next, search for &lt;code&gt;NOTIFICATION_SERVICE&lt;/code&gt;  and insert &amp;ldquo;ifttt&amp;rdquo; there.
The relevant section will then look as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Possible values for NOTIFICATION_SERVICE are: slack, pushover, ifttt, telegram
NOTIFICATION_SERVICE=&amp;#34;ifttt&amp;#34;
NOTIFICATION_FAILURE_ONLY=&amp;#34;yes&amp;#34; # send notifications only if there was an error while creating backup

# ...

# Provider: IFTTT
IFTTT_KEY=&amp;#34;c734bdvJ5afSlnwVRukZZ2&amp;#34; # Key for MAKER channel at IFTTT
IFTTT_MAKER_EVENT=&amp;#34;duplicity&amp;#34; # name the event to trigger at IFTTT Maker Channel
IFTTT_HOOK_URL=&amp;#34;https://maker.ifttt.com/trigger/$IFTTT_MAKER_EVENT/with/key/$IFTTT_KEY&amp;#34; # ONLY change this if IFTTT changes it
IFTTT_VALUE2=&amp;#34;Server11&amp;#34; # general purpose value to pass to your maker channel (optional)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;wrapping-up&#34;&gt;wrapping up&lt;/h2&gt;
&lt;p&gt;While from a security perspective, using mail might be seen favorable as it does not involve trusting an external service, the convenience by not having to setup your own mail client on a server (which may not need it for anything else) out weights the concerns. Also, &lt;a href=&#34;https://ifttt.com&#34;&gt;IFTTT&lt;/a&gt; is a well established service (in operation since 2011), so i feel safe in trusting them with this little information. No password other than the one to IFTTT has been shared.&lt;/p&gt;
&lt;p&gt;Both methods work perfectly fine - however I personally prefer the IFTTT method, as it&amp;rsquo;s easier to setup as it has no additional requirements. In &lt;a href=&#34;../duplicity-backup-email-notifications&#34;&gt;this post&lt;/a&gt; I&amp;rsquo;ve also shown how to configure email notifications directly, so please choose whichever method seems favorable to you.
The most important thing is to be notified should something go wrong with the backup (apart from having a backup!!) - which method is chosen is completely up to the user.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - Google Drive</title>
      <link>https://blog.xmatthias.com/post/duplicity-google-drive/</link>
      <pubDate>Sun, 05 Nov 2017 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-google-drive/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I recommend to first read the &lt;a href=&#34;../duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;../duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post).
You should also visit the &lt;a href=&#34;../duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains a list of all posts in this series.
The basic configuration of &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;google-drive&#34;&gt;Google Drive&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;http://duplicity.nongnu.org/duplicity.1.html&#34;&gt;duplicity manpage&lt;/a&gt; lists multiple ways to use duplicity with Google services:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google Docs
&lt;ul&gt;
&lt;li&gt;Gdata (Legacy backend)&lt;/li&gt;
&lt;li&gt;Pydrive&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Google Cloud Storage&lt;/li&gt;
&lt;li&gt;pydrive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While Google Docs and pydrive backends save the content to Google Drive (using different methods), which comes for free with any Google account - the &lt;a href=&#34;https://cloud.google.com/storage/&#34;&gt;Google Cloud Storage&lt;/a&gt; backend is their paid service. There is a free tier, however this post will focus on Google drive using pydrive.&lt;/p&gt;
&lt;p&gt;Pydrive itself works in 2 ways - by using the regular account (username + password) or with a service account. For now, we will focus on the regular account (it will only save the OAuth-token, not the password / username).&lt;/p&gt;
&lt;h3 id=&#34;getting-started&#34;&gt;Getting started&lt;/h3&gt;
&lt;p&gt;The Google Drive backend requires &lt;a href=&#34;https://pypi.python.org/pypi/PyDrive&#34;&gt;pydrive&lt;/a&gt; (the python package) to be installed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install pydrive
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will also need a Google account.
Go to the &lt;a href=&#34;https://console.developers.google.com&#34;&gt;Google developer console&lt;/a&gt; and &lt;a href=&#34;https://console.developers.google.com/projectcreate&#34;&gt;create a new project&lt;/a&gt;.
Insert a name you&amp;rsquo;d like (I&amp;rsquo;m using &amp;ldquo;duplicity-sync-xmatthias&amp;rdquo; for this demonstration).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_1.png&#34; alt=&#34;duplicity_gm_1&#34;&gt;&lt;/p&gt;
&lt;p&gt;Next, go to the API overview and enable the Google drive API.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_2.png&#34; alt=&#34;duplicity_gm_2&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_3nable_drive.png&#34; alt=&#34;duplicity_gm_3nable_drive&#34;&gt;
After enabling the Drive API, you will be forwarded to the overview of this API.&lt;/p&gt;
&lt;p&gt;Click on credentials on the left hand side and configure the OAuth consent screen to your liking. As only you are going to see this screen, it is important to insert something that is meaningful to, but does not need to be complete.
&lt;img src=&#34;duplicity_gm_oauth.png&#34; alt=&#34;duplicity_gm_oauth&#34;&gt;&lt;/p&gt;
&lt;p&gt;Next, we create a new OAuth Client ID, select other and insert the name for our client (in this case, i used &lt;em&gt;cmd-client&lt;/em&gt;.
&lt;img src=&#34;duplicity_gm_4create_service_key.png&#34; alt=&#34;duplicity_gm_4create_service_key&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_5_client.png&#34; alt=&#34;duplicity_gm_5_client&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now, we are presented with a client-id and a client secret.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_6_client.png&#34; alt=&#34;duplicity_gm_6_client&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Don&amp;rsquo;t bother to try the above keys - by the time this post goes live I already deleted the test application).&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We will paste the client-id and client-secret into the pydrive settings file &amp;ldquo;pydrive.conf&amp;rdquo; as specified on the &lt;a href=&#34;http://duplicity.nongnu.org/duplicity.1.html#sect22&#34;&gt;duplicity manpage&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;client_config_backend: settings
client_config:
    client_id: &amp;lt;Client ID from developers’ console&amp;gt;
    client_secret: &amp;lt;Client secret from developers’ console&amp;gt;
save_credentials: True
save_credentials_backend: file
save_credentials_file: &amp;lt;filename to cache credentials&amp;gt;
get_refresh_token: True
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Ours:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;client_config_backend: settings
client_config:
    client_id: 76061484583-nfoocmj6e891ml1sbmrq7m4gob4b5qht.apps.googleusercontent.com
    client_secret: 8bXpRP9agTBBZiA7X11X6dKk
save_credentials: True
save_credentials_backend: file
save_credentials_file: /home/matt/pydrivecreds.json
get_refresh_token: True
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, we need to export the environment variable so duplicity can find this configuration file&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export GOOGLE_DRIVE_SETTINGS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/home/matt/pydrive.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity full --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB /home/matt pydrive+gdocs://developer.gserviceaccount.com/duplicity_backup_test/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;During this first run, we will be asked to visit a Url. As we do so, we are asked to choose an account - and then allow the application to access the Drive folder.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_8_login.png&#34; alt=&#34;duplicity_gm_8_login&#34;&gt;&lt;/p&gt;
&lt;p&gt;After allowing, we are presented with a code to paste back into the command line.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_7_signedin.png&#34; alt=&#34;duplicity_gm_7_signedin&#34;&gt;&lt;/p&gt;
&lt;p&gt;Press enter and you should see &amp;ldquo;Authentication successful.&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Duplicity will now backup and upload the data.
After the process is complete, we can check what duplicity did by going to &lt;a href=&#34;https://drive.google.com&#34;&gt;Google Drive&lt;/a&gt; and checking the new folder.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;duplicity_gm_9_success.png&#34; alt=&#34;duplicity_gm_9_success&#34;&gt;&lt;/p&gt;
&lt;p&gt;To revoke the application access, go to the &lt;a href=&#34;https://myaccount.google.com/permissions&#34;&gt;Google account Permissions page&lt;/a&gt; and revoke access to the Application (It should show up under whatever name you gave it in the OAuth screen setup - in my case it is &amp;ldquo;duplicity-backup&amp;rdquo;).&lt;/p&gt;
&lt;h2 id=&#34;duplicity-backupsh&#34;&gt;duplicity-backup.sh&lt;/h2&gt;
&lt;p&gt;We can integrate this process fairly easily in the &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity-backup.sh&lt;/a&gt; script this way:&lt;/p&gt;
&lt;p&gt;Change DEST to the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DEST=&amp;#34;pydrive+gdocs://developer.gserviceaccount.com/duplicity_backup_test/&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In addition to this, we also need to export &lt;code&gt;GOOGLE_DRIVE_SETTINGS&lt;/code&gt;.
We do this by adding the following line right below the DEST line.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;export GOOGLE_DRIVE_SETTINGS=/home/matt/pydrive.conf
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The remainder of the configuration remains identical to the configuration used in the &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;duplicity-backup.sh post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We now run the duplicity-backup.sh script.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --backup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything goes well, Google Drive should show the incremental files as well.&lt;/p&gt;
&lt;p&gt;If you still have the cronjob scheduled and used the same configuration file, the backup will automatically go to google Drive instead of the sftp server or a different backend.&lt;/p&gt;
&lt;h2 id=&#34;closing&#34;&gt;Closing&lt;/h2&gt;
&lt;p&gt;This is yet another method to backup your files to a cloud service securely.
Again, the drawback is that the server gains access to your whole Google Drive. Depending on your usage of Google Drive, this may or may not be a problem.
As i don&amp;rsquo;t really use Google Drive for anything else and have plenty of free space available, I am fine with this (The OAuth-tokens saved on the server do only grant access to Google Drive, but to no other Service). Alternatively, you could also create a dedicated account for Duplicity to run the backups.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - Hubic</title>
      <link>https://blog.xmatthias.com/post/duplicity-hubic/</link>
      <pubDate>Tue, 31 Oct 2017 19:20:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-hubic/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I recommend to first read the &lt;a href=&#34;../duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;../duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post).
You should also visit the &lt;a href=&#34;../duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains a list of all posts in this series.
The basic configuration of &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;hubic&#34;&gt;Hubic&lt;/h2&gt;
&lt;p&gt;First of all, we need an account at &lt;a href=&#34;https://hubic.com/home/new/?referral=TXXORL&#34;&gt;hubic.com&lt;/a&gt; (&lt;em&gt;referral link&lt;/em&gt;). More than 25 GB will cost you, however for this tutorial the free account will suffice.&lt;/p&gt;
&lt;p&gt;Using duplicity with the hubic/Rackspace backend requires the &lt;em&gt;Rackspace CloudFiles Pyrax API&lt;/em&gt; library as noted in the &lt;a href=&#34;http://duplicity.nongnu.org/duplicity.1.html#sect30&#34;&gt;duplicity man page&lt;/a&gt;. We can install this by running &lt;code&gt;pip install pyrax&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First, we need to login to hubic and go to My account, and then to Developers. We add a new application (Please note that the application-name must be unique - so best use some random characters).
Also, we need a redirect url, for which we will use &lt;code&gt;http://localhost/&lt;/code&gt;.
&lt;img src=&#34;hubic1.png&#34; alt=&#34;hubic1&#34;&gt;&lt;/p&gt;
&lt;p&gt;We will need the Client ID as well as the Secret Client key from the Application we just created. and insert that in the file &lt;em&gt;~/.hubic_credentials&lt;/em&gt;.
The file should look as below - substitute all variables right of the = sign with the values in your Developers console.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[hubic] 
email = emailididregisterwith@gmail.com 
password = VerySecureRandomOnlinePassword11 
client_id = api_hubic_mVZdgTqLb3ty3BAJZn5Nyk8zBGrN4KVX 
client_secret = QJOvuZe0gHg13ilM3DpCCaNdIlnRUTDa01pbAH5jCfx5BpkpZiu4IAnsuuAnn3Mr 
redirect_uri = http://localhost/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;(Don&amp;rsquo;t bother to try the above keys - by the time this post goes live I already deleted the test application).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As the API requires us to add the password in clear text, we make sure the file is only readable to the user himself by issuing a &lt;code&gt;chmod 600 ~/.hubic_credentials&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Running a first manual test:
&lt;code&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB --ssh-askpass /tmp/backupTest/ &amp;quot;cf+hubic://duplicitybackup1&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This will result in the folder &lt;code&gt;/tmp/backupTest/&lt;/code&gt; to be synchronized to hubic - in the backup-folder duplicitybackup1.
In the web-console of hubic, we go to &amp;ldquo;my backups&amp;rdquo; - where we can see the below backup-files.
&lt;img src=&#34;hubic2.png&#34; alt=&#34;hubic2&#34;&gt;&lt;/p&gt;
&lt;p&gt;As mentioned above, up to 25 GB is free - after that additional storage is available for paying customers.&lt;/p&gt;
&lt;h2 id=&#34;duplicity-backupsh&#34;&gt;duplicity-backup.sh&lt;/h2&gt;
&lt;p&gt;Implementing this into the &lt;code&gt;duplicity-backup.sh&lt;/code&gt; script is as easy as setting the &amp;ldquo;DEST=&amp;rdquo; variable to &amp;ldquo;cf+hubic://duplicityBackup1&amp;rdquo;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DEST=&amp;#34;cf+hubic://duplicityBackup1&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The rest of the configuration remains identical to the configuration used in the &lt;a href=&#34;../duplicity_backup_script/&#34;&gt;duplicity-backup.sh post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We now run the duplicity-backup.sh script.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --full
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you still have the cronjob scheduled and used the same configuration file, the backup will automatically go to hubic instead of the sftp server or a different backend.&lt;/p&gt;
&lt;h2 id=&#34;drawbacks&#34;&gt;Drawbacks&lt;/h2&gt;
&lt;h4 id=&#34;hubic---the-service&#34;&gt;Hubic - the service&lt;/h4&gt;
&lt;p&gt;Hubic is pretty slow - uploading the simple test-folder took quite some time (they seem to implement fairly aggressive rate-limiting. Also, bigger files may not be allowed in the free version. This is not clearly visible - but the next level lists &amp;ldquo;No maximum file size.&amp;rdquo; as an advantage of the Paid version, suggesting that the free version has some limit applied.&lt;/p&gt;
&lt;h4 id=&#34;security&#34;&gt;Security&lt;/h4&gt;
&lt;p&gt;As the password to hubic needs to be saved in clear text in a configuration file (on a server, eventually), it is important to use a unique password, so an attacker would eventually gain access to only this account, and none other.
Also, if duplicity is running on a server (which is a common usecase), you should consider using a dedicated account for backups as well as backing up to another Service as well.
Should the server be breached, one needs to assume the hubic-account also compromised - so an attacker would be able to log in to hubic and delete the backups - essentially making recovery impossible.&lt;/p&gt;
&lt;p&gt;Therefore, I cannot fully recommend using hubic as a backup solution for Servers. Backing up Pictures from your own PC (in addition to other backups!!!) will probably be fine as the data is encrypted with your GPG key.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FULL DISCLOSURE&lt;/strong&gt;
If you register with hubic using the link above, I will get free space added through the referral program. If you want to avoid this, please use &lt;a href=&#34;https://hubic.com&#34;&gt;this&lt;/a&gt; link or type in &lt;a href=&#34;https://hubic.com&#34;&gt;https://hubic.com&lt;/a&gt; into your browser manually.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - Microsoft Onedrive</title>
      <link>https://blog.xmatthias.com/post/duplicity-onedrive/</link>
      <pubDate>Mon, 30 Oct 2017 19:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity-onedrive/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;This is one post in a series of tutorials on Duplicity. If you are just getting started with duplicity, I recommend to first read the &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_getting_started/&#34;&gt;first&lt;/a&gt; and &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_remote/&#34;&gt;second&lt;/a&gt; part to get a basic overview of duplicity and get GPG keys setup properly (this will not be covered in this post).
You should also visit the &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity-backup-going-cloud&#34;&gt;duplicity overview post&lt;/a&gt;, which contains a list of all posts in this series.
The basic configuration of &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_backup_script/&#34;&gt;this post&lt;/a&gt; will be used in this post to configure duplicity-backup.sh.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;microsoft-onedrive&#34;&gt;Microsoft Onedrive&lt;/h2&gt;
&lt;p&gt;In order to get going with &lt;a href=&#34;https://onedrive.live.com?invref=e6e267c6fdf199f8&amp;amp;invscr=90&#34;&gt;Microsoft Onedrive&lt;/a&gt;, we need a Microsoft Account.
The free version offers 5Gb of free storage. Older accounts may have more storage available - more is available for paying customers.&lt;/p&gt;
&lt;p&gt;Using the Onedrive backend requires &lt;code&gt;python-requests&lt;/code&gt; and &lt;code&gt;python-requests-oauthlib&lt;/code&gt; to be installed (as defined on the &lt;a href=&#34;http://duplicity.nongnu.org/duplicity.1.html#sect30&#34;&gt;man page&lt;/a&gt; under Requirements).
Let&amp;rsquo;s simply install them on our system.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt-get install python-requests python-requests-oauthlib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you skip this step and don&amp;rsquo;t have these packages installed, then the execution will fail with the following message:
&lt;code&gt;BackendException: OneDrive backend requires python-requests and python-requests-oauthlib to be installed. Please install them and try again.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s run an initial (manual) test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB  /tmp/backupTest/ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;onedrive://duplicityTest1/backup&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As this is the first time, we will need to go to the link the program shows to confirm the OAuth request.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;onedrive_oauth1.png&#34; alt=&#34;onedrive_oauth1&#34;&gt;&lt;/p&gt;
&lt;p&gt;After confirming by clicking on yes, we need to copy/paste the URL we are forwarded to into duplicity which is waiting/asking for it.
Duplicity will now save the oauth-key, so no further actions are required.
Should you ever want to revoke access to your onedrive account, simply go to the &lt;a href=&#34;https://account.live.com/consent/Manage&#34;&gt;apps and services&lt;/a&gt; page and remove access to duplicity.&lt;/p&gt;
&lt;h2 id=&#34;duplicity-backupsh&#34;&gt;duplicity-backup.sh&lt;/h2&gt;
&lt;p&gt;Implementing this into the &lt;code&gt;duplicity-backup.sh&lt;/code&gt; script is as easy as setting the &amp;ldquo;DEST=&amp;rdquo; Variable to &amp;ldquo;onedrive://duplicityTest1/backup&amp;rdquo;.
The rest of the configuration remains identical to the configuration used in the &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_backup_script/&#34;&gt;duplicity-backup.sh post&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DEST=&amp;#34;onedrive://duplicityTest1/backup1&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Please note that it is necessary to run the first run manually to get OAUTH setup, otherwise the backup-script will not work as duplicity can only log you in if it is run interactively.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We now run the duplicity-backup.sh script again.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --full
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you still have the cronjob scheduled and used the same configuration file, the backup will automatically go to onedrive instead of the sftp server.&lt;/p&gt;
&lt;h2 id=&#34;drawbacks&#34;&gt;Drawbacks&lt;/h2&gt;
&lt;h4 id=&#34;access-level-to-your-onedrive-folder&#34;&gt;access level to your onedrive Folder&lt;/h4&gt;
&lt;p&gt;One downside of Onedrive is that currently you need to grant duplicity access to all your files. I don&amp;rsquo;t expect duplicity to exploit this, however, having the possibility to grant a single, dedicated folder like it is possible with &lt;a href=&#34;https://www.dropbox.com&#34;&gt;Dropbox&lt;/a&gt; would be desirable. Especially if you intend to run duplicity on a server - the OAuth key will need to be saved on that server - which could be a potential problem if sensitive files are in Onedrive and your server is be breached. Fixing this should be easy - the new &lt;a href=&#34;https://docs.microsoft.com/en-us/onedrive/developer/rest-api/concepts/special-folders-appfolder&#34;&gt;API does support&lt;/a&gt; this, but it does not seem to be implemented into the duplicity backend (yet), which is still using the old skydrive API.&lt;/p&gt;
&lt;h4 id=&#34;office-365&#34;&gt;Office 365&lt;/h4&gt;
&lt;p&gt;I also have to say that I did only test onedrive with a personal account, access to a Office 365 Onedrive account may not work (Onedrive personal and Office 365 are called identically, but are 2 separate things when interacting with them on an API level).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FULL DISCLOSURE&lt;/strong&gt;
If you register with onedrive using the link above, i will get free space added through the referral program. If you want to avoid this, please use &lt;a href=&#34;https://onedrive.com&#34;&gt;this&lt;/a&gt; link or type in &lt;a href=&#34;https://onedrive.com&#34;&gt;https://onedrive.com&lt;/a&gt; into your browser manually.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - duplicity-backup.sh</title>
      <link>https://blog.xmatthias.com/post/duplicity_backup_script/</link>
      <pubDate>Thu, 26 Oct 2017 20:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity_backup_script/</guid>
      
      <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_getting_started/&#34;&gt;part 1&lt;/a&gt;, we&amp;rsquo;ve seen how to generate GPG keys and getting started with duplicity.
&lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_remote&#34;&gt;Part 2&lt;/a&gt; covered moving data off the server using sftp and scheduling the jobs using cron.&lt;/p&gt;
&lt;p&gt;In this part, we&amp;rsquo;re going to use an open source &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity script&lt;/a&gt; which will simplify scripting backups as well as eventually restoring files. Until now, we needed to remember the full command line of the duplicity command. This makes handling fairly difficult. The script has a very good readme page - so i recommend to dig deeper into the different options on your own.&lt;/p&gt;
&lt;h2 id=&#34;new-automation-script&#34;&gt;New automation script&lt;/h2&gt;
&lt;p&gt;In order to get the script, we will be using git.
If &lt;code&gt;git --version&lt;/code&gt; shows &amp;ldquo;command not found&amp;rdquo;, install git with &lt;code&gt;sudo apt-get install git&lt;/code&gt;.
Next, we need to clone the github repository and copy the configuration-file example to our own configuration.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/zertrin/duplicity-backup.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd duplicity-backup.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout master
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp duplicity-backup.conf.example duplicity-backup.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script gives us a simple configuration file where all options can be set. The logic is in another file.&lt;/p&gt;
&lt;p&gt;Open the configuration file with your favorite editor and modify the variables &lt;code&gt;ROOT&lt;/code&gt;, &lt;code&gt;DEST&lt;/code&gt;, &lt;code&gt;PASSPHRASE&lt;/code&gt;, &lt;code&gt;INCLIST&lt;/code&gt;, &lt;code&gt;GPG_ENC_KEY&lt;/code&gt;, &lt;code&gt;GPG_SIGN_KEY&lt;/code&gt;, &lt;code&gt;STATIC_OPTIONS&lt;/code&gt;, &lt;code&gt;LOGDIR&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The relevant content of the files should look as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Folder to backup
ROOT=&amp;#34;/tmp/backupTest/&amp;#34;
# Destination
DEST=&amp;#34;sftp://matt@backupserver:1234//home/matt/offsitebackup&amp;#34;

# Password for ssh key
FTP_PASSWORD=&amp;#34;SSHTest1!&amp;#34;

INCLIST=( &amp;#34;*&amp;#34; )
EXCLIST=( &amp;#34;&amp;#34; )

#Passphrase for Signing key
PASSPHRASE=&amp;#34;TestSig1!&amp;#34;
# Encryption key
GPG_ENC_KEY=&amp;#34;3E988E6866B39EE1&amp;#34;
# Signing key
GPG_SIGN_KEY=&amp;#34;E24E7891636093DB&amp;#34;

STATIC_OPTIONS=&amp;#34;--full-if-older-than 14D --s3-use-new-style&amp;#34;

LOGDIR=&amp;#34;/var/log/&amp;#34;
LOG_FILE=&amp;#34;duplicity-$(date +%Y-%m-%d_%H-%M).txt&amp;#34;
LOG_FILE_OWNER=&amp;#34;root:root&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are a lot of other options in the configuration - most have sensible defaults (keeping a total of 4 full backups and cleanup older ones, logging, &amp;hellip;).
&lt;em&gt;Please note that this tutorial is based on the master branch as it was on github on Oct 23rd 2017. The default configuration may change over time as this is a still actively developed project.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After making the above changes, let&amp;rsquo;s try to run the script. The script has pretty good error-checking - making sure folders exist and the permissions are correct.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./duplicity-backup.sh --config duplicity-backup.conf --full
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Depending on how often the backup has been tested before, we may have different outcomes on the cleanup-section. In my case, there were multiple full backups to delete as i tested full backups very often initially.&lt;/p&gt;
&lt;p&gt;Now, we&amp;rsquo;ll replace our crontab-entry we made &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_remote#schedule&#34;&gt;last time&lt;/a&gt; with the new entry:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#old:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#0 1 * * * root /root/backupscript.sh &amp;gt;&amp;gt; /var/log/backupscript.log 2&amp;gt;&amp;amp;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#new:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; * * * root /root/duplicity-backup.sh/duplicity-backup.sh --config /root/duplicity-backup.sh/duplicity-backup.conf &amp;gt;&amp;gt; /var/log/backupscript.log 2&amp;gt;&amp;amp;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script simplifies our life a lot as otherwise we would need to always specify the exact path to the backup location (which can be very frustrating if the remote path is a Amazon S3 bucket or something similar). It would probably be OK for scheduling - but as soon as you need to recover a file, running &lt;code&gt;duplicity-backup.sh [-c config_file] --restore-file backup2/file1&lt;/code&gt; will be a life-changer.&lt;/p&gt;
&lt;h3 id=&#34;backup-script-configuration&#34;&gt;Backup script configuration&lt;/h3&gt;
&lt;p&gt;Run &lt;code&gt;./duplicity-backup.sh --config /root/duplicity-backup.sh/duplicity-backup.conf --backup-script&lt;/code&gt; to backup the configuration and GPG keys - so the restore-process can be migrated to another server easily. This process will ask you for both key passwords, as well as a backup-password (Yes, the backup will be encrypted as well) and show the decryption-instruction on screen.&lt;/p&gt;
&lt;h2 id=&#34;wrapping-up&#34;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;When configuring the backup, always test the backup at least once (best regularly) by restoring to another folder. It&amp;rsquo;s not sufficient to have a backup-process - it&amp;rsquo;s equally important to know that the restores will work as well.
Also, consider setting up one of the mail options - the script can send mails when the process failed - or each time it ran - so you are notified should something go wrong. Otherwise, as long as nothing happens, backups may run in unnoticed in the background for months - only to discover afterwards that there was a problem and the backup did not run in the last days/weeks/months.&lt;/p&gt;
&lt;p&gt;I may cover setting up email notifications in a future blogpost.&lt;/p&gt;
&lt;p&gt;In the next part, we will take a look at some of the different cloud-based-options duplicity offers and how to configure them with the duplicity-backup script.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - remote backup</title>
      <link>https://blog.xmatthias.com/post/duplicity_remote/</link>
      <pubDate>Sun, 22 Oct 2017 21:15:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity_remote/</guid>
      
      <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;In the &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_getting_started/&#34;&gt;first part&lt;/a&gt; of the duplicity series, we saw how to create GPG keys, create encrypted and signed backups locally and restore them.
Now, we are going to move data off the server (so we have an offsite-backup).
Also, we will schedule the backup using cron so the backup is run nightly.&lt;/p&gt;
&lt;p&gt;I like to manually run the commands before scripting stuff, so i fully understand what is happening and can discover problems before the script is failing daily. Therefore, the script implementation will be the last step.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: As in the first part, this tutorial will use root on the local system. On the remote system, the user &amp;ldquo;matt&amp;rdquo; will be used.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;sftp&#34;&gt;sftp&lt;/h2&gt;
&lt;p&gt;First, let&amp;rsquo;s make sure we can connect to the backup-server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# ssh backupuser@backupserver [-p port]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have not yet created the SSH keys (we will do this in the next step) - then this should ask for the password of the remote user.&lt;/p&gt;
&lt;p&gt;Next - let&amp;rsquo;s try to run a full backup.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# duplicity --encrypt-key [encrypt-key] --sign-key [sign-key] --ssh-askpass [folder-to-backup] sftp://[user]@[backupserver]:[port]//[folderonremotehost]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB --ssh-askpass /tmp/backupTest/ sftp://matt@backupserver:1234//home/matt/offsitebackup 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please note that the port can be omitted if the default SSH port (22) is used. This will again ask for the remote users password, as well as the password for the Sign-key, so we need to be carefull when we insert which password.&lt;/p&gt;
&lt;p&gt;Restore / verify operations follow the same logic as explained in the &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_getting_started/&#34;&gt;first part&lt;/a&gt; but by exchanging the target plugin &lt;em&gt;file://[targetfolder]&lt;/em&gt; with &lt;em&gt;sftp://[targetfolder]&lt;/em&gt;.
To check that the backup was indeed made, SSH into the backup server and check the backup-folder (&lt;code&gt;ls -l /home/matt/offsitebackup&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;Now this was easy - now let&amp;rsquo;s wrap this into a little script which can run automatically.&lt;/p&gt;
&lt;h2 id=&#34;ssh-keys&#34;&gt;SSH Keys&lt;/h2&gt;
&lt;p&gt;For the following scripts to work, we will need password-less SSH setup.
This is as easy as running the following command and accepting all defaults.
As this key allows everyone in possession of the key to login to the remote server, we will use the password &lt;em&gt;SSHTest1!&lt;/em&gt; as password for the key. As always, this is a sample password with the intend to be easy and clear to the reader, in reality I am using a much stronger password.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-keygen -b &lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt; -t rsa
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the key is generated, we copy the key to the target server with the following command.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#ssh-copy-id [user]@[targethost] -p [port]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-copy-id matt@backupserver -p &lt;span style=&#34;color:#ae81ff&#34;&gt;1234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we test access using the key:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;user&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;@&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;targethost&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; -p &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;port&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh matt@backupserver -p &lt;span style=&#34;color:#ae81ff&#34;&gt;1234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything is working correctly, you should see the welcome message from the backup server.&lt;/p&gt;
&lt;h2 id=&#34;first-script-selfmade&#34;&gt;First script (selfmade)&lt;/h2&gt;
&lt;p&gt;We will now put what we learned into a very simple script.
In the next part, we will switch to a better version of the script - but for now we do it &amp;ldquo;all by ourselves&amp;rdquo;.
Open your favorite editor and paste the following script to a new file called backupscript.sh.
Please use your secure password and key-id&amp;rsquo;s you generated in &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_getting_started/&#34;&gt;part 1&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# passwod to ssh key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export FTP_PASSWORD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;SSHTest1!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# password to the encrypt key - set to empty so duplicity is not asking&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export PASSPHRASE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# password to the Sign key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export SIGN_PASSPHRASE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TestSig1!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ENCRYPT_KEY&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;3E988E6866B39EE1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SIGN_KEY&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;E24E7891636093DB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Local source folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SOURCE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/tmp/backupTest/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# (remote) target folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TARGET&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sftp://matt@backupserver:1234//home/matt/offsitebackup&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity --full-if-older-than 5D --encrypt-key &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;ENCRYPT_KEY&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; --sign-key &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;SIGN_KEY&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;SOURCE&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;TARGET&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make the file executable by running &lt;code&gt;chmod +x backupscript.sh&lt;/code&gt;.
To keep the passwords to ourselves (the root user) - we also modify the permissions to disallow everything from other users &lt;code&gt;chmod 700 backupscript.sh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the script, I also added the option &lt;code&gt;--full-if-older-than 5D&lt;/code&gt; - which we did not use before and has duplicity do a full backup if the last full backup is older than 5 days.&lt;/p&gt;
&lt;p&gt;let&amp;rsquo;s run the script&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./backupscript.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h5 id=&#34;output&#34;&gt;output:&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./backupscript.sh 
Local and Remote metadata are synchronized, no sync needed.
Last full backup date: Sat Oct 21 10:54:06 2017
--------------[ Backup Statistics ]--------------
StartTime 1508576169.90 (Sat Oct 21 10:56:09 2017)
EndTime 1508576169.96 (Sat Oct 21 10:56:09 2017)
ElapsedTime 0.06 (0.06 seconds)
SourceFiles 61
SourceFileSize 45086 (44.0 KB)
NewFiles 0
NewFileSize 0 (0 bytes)
DeletedFiles 0
ChangedFiles 0
ChangedFileSize 0 (0 bytes)
ChangedDeltaSize 0 (0 bytes)
DeltaEntries 0
RawDeltaSize 0 (0 bytes)
TotalDestinationSizeChange 732 (732 bytes)
Errors 0
-------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As we can see, the backup completed successfully.
We can try a restore (documentation on that is in &lt;a href=&#34;https://blog.xmatthias.com/post/duplicity_getting_started/&#34;&gt;part 1&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&#34;schedule&#34;&gt;Schedule&lt;/h2&gt;
&lt;p&gt;It is important to run backups regularly - therefore we will now use &amp;ldquo;crontab&amp;rdquo; to schedule the backup process.
There are 2 possibilities to schedule tasks with crontab - either by user &lt;code&gt;crontab -e&lt;/code&gt;  or in the file &lt;em&gt;/etc/crontab&lt;/em&gt;.
I will be using /etc/crontab for this tutorial. This means, only super-users (root) can change the schedule (or disable backups) - however we can still define which user the backup should run as.
As the initial explanation in the file says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unlike any other crontab you don&amp;rsquo;t have to run the `crontab&amp;rsquo; command to install the new version when you edit this file and files in /etc/cron.d. These files also have username fields, that none of the other crontabs do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&amp;rsquo;s open the crontab file (we need to be root for this, so prefix the command with sudo).
and add the following line at the end:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# m h dom mon dow user	command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 0 1 * * * [user] [full_path_to_backup_script] &amp;gt;&amp;gt; [path_to_log_file] 2&amp;gt;&amp;amp;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; * * * root /root/backupscript.sh &amp;gt;&amp;gt; /var/log/backupscript.log 2&amp;gt;&amp;amp;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By using &lt;code&gt;0 1 * * *&lt;/code&gt;  we run this backup-script daily at 1 am. Also, we specify &lt;code&gt;/var/log/backupscript.log&lt;/code&gt; as log-file. We can now wait overnight and then check the log-file. The content will be similar to the output above.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This was fairly simple - however haven&amp;rsquo;t reached our final goal yet. Remember, we wanted to have 3 copies of our data, in at least 2 different locations, with at least 1 backup offsite. Until now, we either have a backup on the same server (which will not help much in case of a server crash) - or a backup at a remote server (which may be inconvenient if we delete a wrong file by accident).&lt;/p&gt;
&lt;p&gt;In the next part, we will switch from our home-made quick and dirty script to a open source &lt;a href=&#34;https://github.com/zertrin/duplicity-backup.sh&#34;&gt;duplicity-backup&lt;/a&gt; script which gives us more options out of the box without the need to reinvent the wheel.
Also, we will have a look at the &amp;ldquo;multi&amp;rdquo; duplicity plugin, which allows us to specify multiple targets for the same backup.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>duplicity backup - getting started</title>
      <link>https://blog.xmatthias.com/post/duplicity_getting_started/</link>
      <pubDate>Tue, 17 Oct 2017 20:01:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/duplicity_getting_started/</guid>
      
      <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A basic rule for Backups is the 3-2-1 rule: &lt;strong&gt;3&lt;/strong&gt; total copies of the data - on &lt;strong&gt;2&lt;/strong&gt; different mediums, at least &lt;strong&gt;1&lt;/strong&gt; offsite.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the following multi-part tutorial I will show how to generate fairly secure backups with duplicity following the above strategy.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: My test-system is debian-based - however the commands should also work with most other Linux systems by replacing the name of the package-manager to the system-default.
The tutorial will assume that you have root access on the system. Most steps are also possible as regular user - however full system backups are not possible in this case.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;about-duplicity&#34;&gt;About duplicity&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;http://duplicity.nongnu.org/duplicity.1.html&#34;&gt;Duplicity&lt;/a&gt; is a python-based backup-program which has multiple backends. It uses encryption by default and handles the gpg encryption for us.
The signature-key defaults to the encryption-key - in that case, the encryption-key is used for signing as well. I strongly recommend to create a separate Keypair - the following will assume you will do the same.&lt;/p&gt;
&lt;h3 id=&#34;encryption-and-keys&#34;&gt;Encryption and keys&lt;/h3&gt;
&lt;p&gt;Duplicity is able use 2 different methods of encryption.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;symmetric encryption&lt;/li&gt;
&lt;li&gt;asymmetric encryption&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This post will focus on asymmetric encryption as this is considered more secure than symmetric encryption (it uses a different key for encryption and decryption).
Explaining the cryptographic details would span a whole book, so I&amp;rsquo;ll leave further research to the interested reader as there are many good resources on this topic available.&lt;/p&gt;
&lt;p&gt;To ideally protect our backup, we will be generating 2 GPG key-pairs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;encryption key pair (confidentiality)&lt;/li&gt;
&lt;li&gt;signing key pair (integrity)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While backing up, the public key of the &lt;strong&gt;encryption&lt;/strong&gt; key pair is used to encrypt the data, while the private key of the &lt;strong&gt;signing&lt;/strong&gt; key pair will be used to ensure the integrity of the backup.&lt;/p&gt;
&lt;p&gt;We will use separate keys as the pass-phrase for the signing key needs to be available when running the backup (which is normally a script or scheduled job).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s first make sure we have enough entropy for the key generation.&lt;/p&gt;
&lt;h4 id=&#34;generating-keys---entropy&#34;&gt;generating keys - entropy&lt;/h4&gt;
&lt;p&gt;Note: the key-generation may take a while, depending on the available entropy in the system (check using &lt;code&gt;cat /proc/sys/kernel/random/entropy_avail&lt;/code&gt;).
On a fresh test-system I faced this problem, while on my regular PC i had enough entropy available.&lt;/p&gt;
&lt;p&gt;The following should be run in a separate session and generate enough entropy&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get install rng-tools
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rngd -f -r /dev/urandom
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;generating-the-keys&#34;&gt;Generating the keys&lt;/h4&gt;
&lt;p&gt;For this tutorial, I will use the passwords &lt;em&gt;TestEnc1!&lt;/em&gt; for the Encryption key (named &lt;em&gt;duplicity_enc&lt;/em&gt;), and &lt;em&gt;TestSig1!&lt;/em&gt; for the signing key (named &lt;em&gt;duplicity_sign&lt;/em&gt;).
In reality, a random, secure password/pass phrase should be used (this passwords have multiple problems - please never use such passwords for anything). Also, please consider using 4096 bit keysize - this will increase security another bit (i did stick with defaults for this tutorial - but my production implementation does use 4096 bit keysizes).&lt;/p&gt;
&lt;p&gt;We will need to run the following command twice, once for the encryption key pair and once for the signing key pair. Make sure to use different passwords, otherwise a single key could be used as well.&lt;/p&gt;
&lt;p&gt;Note that the signing-key needs to be generated first.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpg --full-generate-key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;sample output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 bits
Please specify how long the key should be valid.
         0 = key does not expire
      &amp;lt;n&amp;gt;  = key expires in n days
      &amp;lt;n&amp;gt;w = key expires in n weeks
      &amp;lt;n&amp;gt;m = key expires in n months
      &amp;lt;n&amp;gt;y = key expires in n years
Key is valid for? (0) 
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: duplicity_sign
Email address: 
Comment: Test key for duplicity signing
You selected this USER-ID:
    &amp;#34;duplicity_sign (Test key for duplicity signing)&amp;#34;

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key E24E7891636093DB marked as ultimately trusted
gpg: revocation certificate stored as &amp;#39;/root/.gnupg/openpgp-revocs.d/5BA6FC44F5C7FBF5CCB62A43E24E7891636093DB.rev&amp;#39;
public and secret key created and signed.

pub   rsa2048 2017-10-15 [SC]
      5BA6FC44F5C7FBF5CCB62A43E24E7891636093DB
uid                      duplicity_sign (Test key for duplicity signing)
sub   rsa2048 2017-10-15 [E]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After generating both keys, the output of &lt;code&gt;gpg --list-keys --keyid-format long&lt;/code&gt; should look similar to mine:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/root/.gnupg/pubring.kbx
-----------------------------
pub   rsa2048/E24E7891636093DB 2017-10-15 [SC]
      5BA6FC44F5C7FBF5CCB62A43E24E7891636093DB
uid                 [ultimate] duplicity_sign (Test key for duplicity signing)
sub   rsa2048/1118A69B4088EC29 2017-10-15 [E]

pub   rsa2048/3E988E6866B39EE1 2017-10-15 [SC]
      1FD28DA009BBEE82A543B2CC3E988E6866B39EE1
uid                 [ultimate] duplicity_enc (test key for duplicity encryption)
sub   rsa2048/74DCEA71B0217B9B 2017-10-15 [E]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The interesting part is &lt;strong&gt;E24E7891636093DB&lt;/strong&gt; and &lt;strong&gt;1118A69B4088EC29&lt;/strong&gt;, which contains our key-id&amp;rsquo;s. The key-id&amp;rsquo;s will be unique for everyone running though this tutorial - the keys must be replaced with your own for every step they appear in.&lt;/p&gt;
&lt;p&gt;Next, we will need to sign the encryption key.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpg --sign-key duplicity_enc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sec  rsa2048/3E988E6866B39EE1
     created: 2017-10-15  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa2048/74DCEA71B0217B9B
     created: 2017-10-15  expires: never       usage: E   
[ultimate] (1). duplicity_enc (test key for duplicity encryption)


sec  rsa2048/3E988E6866B39EE1
     created: 2017-10-15  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
 Primary key fingerprint: 1FD2 8DA0 09BB EE82 A543  B2CC 3E98 8E68 66B3 9EE1

     duplicity_enc (test key for duplicity encryption)

Are you sure that you want to sign this key with your
key &amp;#34;duplicity_sign (Test key for duplicity signing)&amp;#34; (E24E7891636093DB)

Really sign? (y/N) y
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;backup-gpg-keys&#34;&gt;backup GPG keys&lt;/h5&gt;
&lt;p&gt;Export public keys and store them in a safe location (if you loose them you cannot get your files back).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# gpg --armor --export -a [keyid] &amp;gt; [public_key_filename].key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpg --armor --export -a 5BA6FC44F5C7FBF5CCB62A43E24E7891636093DB &amp;gt; duplicity_sign_public.key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpg --armor --export -a 1FD28DA009BBEE82A543B2CC3E988E6866B39EE1 &amp;gt; duplicity_enc_public.key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Export public keys and store them in a safe location. This will ask you for the passwords/pass phrases provided above.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# gpg --armor --export-secret-keys -a [keyid] &amp;gt; [private_key_filename].key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpg --armor --export-secret-keys -a 5BA6FC44F5C7FBF5CCB62A43E24E7891636093DB &amp;gt; duplicity_sign_private.key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpg --armor --export-secret-keys -a 1FD28DA009BBEE82A543B2CC3E988E6866B39EE1 &amp;gt; duplicity_enc_private.key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Details about the gpg key restore process may be shared in a later post.&lt;/p&gt;
&lt;h4 id=&#34;install-duplicity&#34;&gt;install duplicity&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get install duplicity
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s create a few test folders with 5 files in each folder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir backupTest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd backupTest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir backup&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;1..10&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch backup&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;1..10&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;/file&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;1..5&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;backupTest
|-- backup1
|-- backup1/file1
|-- backup1/file2
|-- backup1/file3
|-- backup2/file1
...
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;first-test&#34;&gt;first test&lt;/h4&gt;
&lt;p&gt;To start, we&amp;rsquo;ll backup the folder /tmp/backupTest to /tmp/backup.
This will ask for the password to the &lt;strong&gt;signing&lt;/strong&gt; key (we are ready to script the backup - let&amp;rsquo;s test things manually for now).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# duplicity full --encrypt-key [encryptkey] --sign-key [signkey] [folder] file://[backupfolder]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity full --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB /tmp/backupTest file:///tmp/backup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the target-folder has 3 &amp;ldquo;/&amp;rdquo; - this is because I&amp;rsquo;m using absolute paths here.&lt;/p&gt;
&lt;p&gt;To verify the backup run &lt;code&gt;duplicity verify&lt;/code&gt; (Target folder and folder are reversed).
This will ask for the password of our &lt;strong&gt;encryption&lt;/strong&gt; key.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# duplicity verify --compare-data --encrypt-key [encryptkey] --sign-key [signkey] file://[backupfolder] [folder] &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity verify --compare-data --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB file:///tmp/backup /tmp/backupTest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;--compare-data&lt;/code&gt; compares the actual content of the files, not just the files themselves. For remote connections and big backups this is not recommended.&lt;/p&gt;
&lt;p&gt;Now, lets change a file &lt;code&gt;echo test &amp;gt; backup2/file2&lt;/code&gt; and rerun the above verify command.&lt;/p&gt;
&lt;p&gt;Now the output should show a difference.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Local and Remote metadata are synchronized, no sync needed.
Last full backup date: Sun Oct 15 20:14:03 2017
GnuPG passphrase for decryption: 
Difference found: File backup2/file2 has mtime Sun Oct 15 20:15:15 2017, expected Sun Oct 15 13:10:53 2017
Verify complete: 61 files compared, 1 difference found.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;em&gt;1 difference found&lt;/em&gt; highlights the difference we just created.
Running the incremental sync again will remove this difference again.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# duplicity incr --encrypt-key [encryptkey] --sign-key [signkey] [folder] file://[backupfolder]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;duplicity incr --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB /tmp/backupTest file:///tmp/backup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;output:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Local and Remote metadata are synchronized, no sync needed.
Last full backup date: Sun Oct 15 20:14:03 2017
GnuPG passphrase for decryption: 
GnuPG passphrase for signing key: 
--------------[ Backup Statistics ]--------------
StartTime 1508091392.03 (Sun Oct 15 20:16:32 2017)
EndTime 1508091392.11 (Sun Oct 15 20:16:32 2017)
ElapsedTime 0.07 (0.07 seconds)
SourceFiles 61
SourceFileSize 45086 (44.0 KB)
NewFiles 0
NewFileSize 0 (0 bytes)duplicity-backup.conf_mine
DeletedFiles 0
ChangedFiles 1
ChangedFileSize 10 (10 bytes)
ChangedDeltaSize 0 (0 bytes)
DeltaEntries 1
RawDeltaSize 15 (15 bytes)
TotalDestinationSizeChange 833 (833 bytes)
Errors 0
-------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we have one full backup - and one additional partial backup.&lt;/p&gt;
&lt;p&gt;looking into our backup-folder we see the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-rw------- 1 root root 1758 Oct 15 20:14 duplicity-full-signatures.20171015T181403Z.sigtar.gpg
-rw------- 1 root root 1001 Oct 15 20:14 duplicity-full.20171015T181403Z.manifest.gpg
-rw------- 1 root root 1527 Oct 15 20:14 duplicity-full.20171015T181403Z.vol1.difftar.gpg
-rw------- 1 root root  823 Oct 15 20:16 duplicity-inc.20171015T181403Z.to.20171015T181625Z.manifest.gpg
-rw------- 1 root root  833 Oct 15 20:16 duplicity-inc.20171015T181403Z.to.20171015T181625Z.vol1.difftar.gpg
-rw------- 1 root root  846 Oct 15 20:16 duplicity-new-signatures.20171015T181403Z.to.20171015T181625Z.sigtar.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We see that we have one full sync - and one incremental sync.&lt;/p&gt;
&lt;h3 id=&#34;restore&#34;&gt;restore&lt;/h3&gt;
&lt;p&gt;Testing the backup (aka restoring) is important to be sure the backups are working.
Restoring with duplicity is as simple as inverting the backup-command (without full / incr keyword) and supplying the password to the &lt;strong&gt;encryption&lt;/strong&gt; key.
For completeness, we will include the restore-keyword to make the intent obvious.&lt;/p&gt;
&lt;p&gt;My restore will go to the path /tmp/test2. Restoring to a non-empty path will result in the message &amp;ldquo;Will not overwrite.&amp;rdquo;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# duplicity restore --encrypt-key [encryptkey] --sign-key [signkey] file://[backupfolder] [folder] 
duplicity restore --encrypt-key 3E988E6866B39EE1 --sign-key E24E7891636093DB  file:///tmp/backup /tmp/test2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This folder now contains the same content than /tmp/backupTest. The restore-process also restores file permissions - which is very handy for full system backups.&lt;/p&gt;
&lt;h3 id=&#34;final-note&#34;&gt;Final note&lt;/h3&gt;
&lt;p&gt;While testing the encryption I ran into some unexpected problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;i used the wrong key-id (wrong format) for encryption, so decryption was not possible anymore. Instructions i found on the Internet were not very clear in this regard.&lt;/li&gt;
&lt;li&gt;i thought that the restore / decryption would not require a password (which would be a big no go). The problem turned out to be caching of the GPG agent, which had the file loaded after the first run.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In total, the above problems cost me about an hour.
In the next part, we will look at offsite-backups (transferring the backup to another server).&lt;/p&gt;
&lt;p&gt;Hope you learned some&lt;/p&gt;
&lt;p&gt;Matthias&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Security considerations while blogging</title>
      <link>https://blog.xmatthias.com/post/security-vs-openness/</link>
      <pubDate>Tue, 10 Oct 2017 20:10:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/security-vs-openness/</guid>
      
      <description>&lt;p&gt;Blogging about the blog/server-setup is a fairly difficult topic for me.&lt;/p&gt;
&lt;p&gt;On one side, I&amp;rsquo;d like to share how i set things up so others can get started easily (and hopefully rather securely), while on the other side, I fear that going into too much depth will open up my site / infrastructure to attacks as this simplifies information gathering. I would not want to deliver my site to attackers on a silver plate - at least have them work for the informations. In the end, most bad guys are financially motivated - once the cost of attack is higher than the benefit, most will look for easier targets.&lt;/p&gt;
&lt;h3 id=&#34;how-i-will-handle-it-in-this-blog&#34;&gt;how I will handle it in this blog&lt;/h3&gt;
&lt;p&gt;I will try to keep the balance (sharing as much as possible, without exposing all details).
Decisions about which details i will write about, and which i will only touch slightly will be made case by case (or post by post-basis).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll also keep it as transparent as possible if all details are posted or not.&lt;/p&gt;
&lt;p&gt;I hope my posts will still help some people get started securely.&lt;/p&gt;
&lt;p&gt;cheers
Matthias&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Switching keyboard layout - quick update after 5 days</title>
      <link>https://blog.xmatthias.com/post/switching-keyboard-layout-update-after-5-days/</link>
      <pubDate>Tue, 03 Oct 2017 22:00:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/switching-keyboard-layout-update-after-5-days/</guid>
      
      <description>&lt;p&gt;As I pointed out in my &lt;a href=&#34;https://blog.xmatthias.com/post/switching-keyboard-layout/&#34;&gt;post&lt;/a&gt; last week, I switched keyboard layout to english on all my machines.&lt;/p&gt;
&lt;p&gt;So far it&amp;rsquo;s been going better than expected - I only thought about reverting back once while beeing in a rush and constantly missing the same symbol (semicolon) - however resisted the urge and am now mostly confident in what I type.
It still requires some concentration to not fall back to the layout I&amp;rsquo;m used to - however it&amp;rsquo;s far less obstructive than I immagined.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it for today,
read you soon&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Switching keyboard layout</title>
      <link>https://blog.xmatthias.com/post/switching-keyboard-layout/</link>
      <pubDate>Thu, 28 Sep 2017 20:20:12 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/switching-keyboard-layout/</guid>
      
      <description>&lt;p&gt;A colleague of mine recently told me&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;You as a developer should consider switching to english keyboard layout - most programming languages have probably been developed by people with english keyboard-layouts - so language-specific buttons will be reachable much easier than on the german keyboard.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Having used a german keyboard most of my life I could not deny a certain logic to it. Also - It&amp;rsquo;s been a while since I got used to switching layouts from time to time (default keyboard on a newly installed linux is english - and it helps to be able to get out of vi without googling &amp;ldquo;where is : on the UK keyboard&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;m almost never writing in german anyway it should not matter much to loose the &amp;ldquo;Umlaute&amp;rdquo; - but help me in the long run to type faster.
With this background I decided this morning to switch to the UK keyboard layout (the layout is identical to german - but most programming-specific keys are reachable without 3-button combos).
So far it&amp;rsquo;s working mostly fine - just y/z are sometimes swapped - I guess i can get used to this layout within another day or 2.
I still keep the layout-table open in a browser tab (i only swapped the layout - not the physical keyboard) so i can have a quick look if i can&amp;rsquo;t find a key.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll try and post an update later on if I could successfully stick with it or if i reverted back to my comfort zone.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Check if shell-script is runing with root permissions (or with sudo)</title>
      <link>https://blog.xmatthias.com/post/check-if-shell-script-is-runing-with-root-permissions-or-with-sudo/</link>
      <pubDate>Sun, 24 Sep 2017 11:31:48 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/check-if-shell-script-is-runing-with-root-permissions-or-with-sudo/</guid>
      
      <description>&lt;p&gt;Some scripts need to run as root (iptables for temporary rules, installer scripts, &amp;hellip;).
A quick way to check if the shell-script is running as root or with sudo (sudo should be the preferred way) is as follows.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; ! &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;EUID&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; -eq &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Please run as root or with sudo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  exit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;this has been tested tested on debian-based and arch-linux, but should also work on most other linux derivates.&lt;/p&gt;
&lt;p&gt;it&amp;rsquo;s not new - but i was not aware of it until recently.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Compiling python 3.6 for centos 5.11 with openssl</title>
      <link>https://blog.xmatthias.com/post/compiling-python-3-6-for-centos-5-11-with-openssl/</link>
      <pubDate>Mon, 18 Sep 2017 18:31:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/compiling-python-3-6-for-centos-5-11-with-openssl/</guid>
      
      <description>&lt;p&gt;Lately I was about to develop and deploy a python-script to a company-server (internal and firewalled) which is still running Centos 5.11.&lt;/p&gt;
&lt;p&gt;My first reaction was &amp;ldquo;can we upgrade to a newer system&amp;rdquo; - however at this time this is not an option.&lt;/p&gt;
&lt;p&gt;Before doing this on the server, i ran multiple tests in a docker-image as this server does not have a test-instance.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -it centos:centos5 /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As centos5 has reached End of Life, some tweaking was needed to get yum in the container to behave as expected as the repositories were moved to &amp;ldquo;vault&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;There are cleaner/better ways to do this - but it works for this demonstration.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir /var/cache/yum/base/ &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; mkdir /var/cache/yum/extras/ &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; mkdir /var/cache/yum/updates/ &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; mkdir /var/cache/yum/libselinux/ &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://vault.centos.org/5.11/os/x86_64/&amp;#34;&lt;/span&gt; &amp;gt; /var/cache/yum/base/mirrorlist.txt &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://vault.centos.org/5.11/extras/x86_64/&amp;#34;&lt;/span&gt; &amp;gt; /var/cache/yum/extras/mirrorlist.txt &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://vault.centos.org/5.11/updates/x86_64/&amp;#34;&lt;/span&gt; &amp;gt; /var/cache/yum/updates/mirrorlist.txt &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://vault.centos.org/5.11/centosplus/x86_64/&amp;#34;&lt;/span&gt; &amp;gt; /var/cache/yum/libselinux/mirrorlist.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Installing dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum install -y gcc gcc44 zlib-devel python-setuptools readline-devel wget make perl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After some trial and error i discovered that openssl is necessary to even get pip to work properly (it requires openssl unless you want to use &amp;ldquo;&amp;ndash;trusted-host&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;To get python to compile correctly with openssl, compiling openssl with a specific flag was necessary (please note that openssl 1.0.xx was used as openssl 1.1.xx causes perl-dependencies on this legacy system).&lt;/p&gt;
&lt;h3 id=&#34;openssl&#34;&gt;openssl&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# download openssl - please check https://www.openssl.org/source/ for the latest 1.0.21 version.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://www.openssl.org/source/openssl-1.0.2l.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar xzvpf openssl-1.0.2l.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd openssl-1.0.2l
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./config --prefix&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/usr/local/ssl --openssldir&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/usr/local/ssl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#modify Makefile to include -fPIC in CFLAGS # similar to export CFLAGS=-fPIC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sed -i.orig &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/^CFLAG/s/$/ -fPIC/&amp;#39;&lt;/span&gt; Makefile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; make test &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; make install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;python&#34;&gt;python&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;##python:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MAJORVERS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;3.6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VERSION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# https://superuser.com/questions/646455/how-to-fix-decimal-module-compilation-error-when-installing-python-3-3-2-in-cen&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export CC&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/usr/bin/gcc44
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://www.python.org/ftp/python/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/Python-&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;.tgz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar xzvf Python-&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;.tgz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd Python-&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To enable openssl in Modules/Setup.dist (based on this &lt;a href=&#34;https://techglimpse.com/install-python-openssl-support-tutorial/&#34;&gt;instruction&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Change the following section from this&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-None&#34; data-lang=&#34;None&#34;&gt;#_socket socketmodule.c

# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
#SSL=/usr/local/ssl
#_ssl _ssl.c \
# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
# -L$(SSL)/lib -lssl -lcrypto
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;to&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-None&#34; data-lang=&#34;None&#34;&gt;# Socket module helper for socket(2)
_socket socketmodule.c

# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
#SSL=/usr/local/ssl
_ssl _ssl.c \
-DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
-L$(SSL)/lib -lssl -lcrypto
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;build and install as alternative version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./configure --prefix&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/opt/python&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; make altinstall
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# link the alternative binaries into a location in $PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ln -s /opt/python&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/bin/python&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; /usr/local/bin/python&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ln -s /opt/python&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/bin/pip&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; /usr/local/bin/pip&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MAJORVERS&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;run your newly installed python:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/opt/python3.6/bin/python3.6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Try to import the ssl module - if this works then python with openssl is installed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; ssl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This guide is far from perfect - but so is having to deal with Centos5 in 2017.
It installs python3.6 with openssl in Centos5.&lt;/p&gt;
&lt;p&gt;Hope this helps someone passing by here.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Using App.xaml in .dll-assembly</title>
      <link>https://blog.xmatthias.com/post/using-app-xaml-in-dll-assembly/</link>
      <pubDate>Wed, 13 Sep 2017 10:30:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/using-app-xaml-in-dll-assembly/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;m currently working on a wpf-application cooperating with another company. We have only part of the sourcecode and therefore only compile a few .dll&amp;rsquo;s, the main executable however get&amp;rsquo;s shipped to us as finished product.&lt;/p&gt;
&lt;p&gt;The application uses style-files that get loaded at startup by the main application from files in a specific folder, therefore we faced a the problem that these styles don&amp;rsquo;t get applied at design-time, but only at runtime.&lt;/p&gt;
&lt;h3 id=&#34;the-problem&#34;&gt;The Problem:&lt;/h3&gt;
&lt;p&gt;While changing tons of stuff for a new UI we are working on I started using a new user-control (which derrives from button) in order to have a consistant layout all over the app. The default style sadly had the height set to &amp;ldquo;auto&amp;rdquo;, which caused the layouts to be very weired during design-time, but work at runtime (because of the applied style which sets the height to the desired value). Fixing this was a priority as our design-team struggled with the messed up designs.&lt;/p&gt;
&lt;p&gt;To fix this i had tree possibilities - eighter set the correct height for each button manually (which the design-team started to do), include a style at each control we&amp;rsquo;re editing, or load resources in an App.xaml. Hardcoding the height is neighter elegant nor usable as i suspected the size of the buttons to be changed at a later point (and i was proven right later on).&lt;/p&gt;
&lt;p&gt;I decided to go for the last approach as this seemed to be the easyest and fastest. However - we&amp;rsquo;re not compiling the main executable, only a .dll (which does not have a app.xaml where you can define the styles).&lt;/p&gt;
&lt;h3 id=&#34;the-solution&#34;&gt;The Solution&lt;/h3&gt;
&lt;p&gt;Seaching the web i found a working solution at &lt;a href=&#34;http://blogs.msdn.com/b/expression/archive/2008/04/09/creating-a-wpf-blend-project-that-loads-resources-in-code.aspx&#34;&gt;The team blog of the Expression Blend and Design products.&lt;/a&gt; The team blog of the Expression Blend and Design products&lt;!-- raw HTML omitted --&gt;. That page suggests that using App.xaml is possible for .dll-files at designtime (using them only during design-time, and excluding them at compile-time). To get this working well for us i had to make a few changes as we don&amp;rsquo;t use one style-file but have the styles and themes separated in many files and load them as resources, using it as shown in the example would have caused lots of issues when adding new files. however the principle is quite easy and easily understandable:&lt;/p&gt;
&lt;p&gt;open the &lt;code&gt;.csproj&lt;/code&gt; of your project and insert the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;ItemGroup&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Condition=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#39;$(DesignTime)&amp;#39;==&amp;#39;true&amp;#39; AND
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;              &amp;#39;$(BuildingInsideVisualStudio)&amp;#39;!=&amp;#39;true&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;               AND &amp;#39;$(BuildingInsideExpressionBlend)&amp;#39;!=&amp;#39;true&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;Resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Include=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Skins\DesignTimeTheme.xaml&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;Generator&amp;gt;&lt;/span&gt;MSBuild:Compile&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/Generator&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;SubType&amp;gt;&lt;/span&gt;Designer&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/SubType&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/Resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;Compile&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Include=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;App.xaml.cs&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;DependentUpon&amp;gt;&lt;/span&gt;App.xaml&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/DependentUpon&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;DesignTime&amp;gt;&lt;/span&gt;true&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/DesignTime&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/Compile&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;explanation&#34;&gt;Explanation:&lt;/h3&gt;
&lt;p&gt;Adding the condition to the ItemGroup applies that to all resources that lie below. That means, i have the App.xaml and the Theme there only at design-time, but they&amp;rsquo;ll be excluded at runtime. The advantage of this is that upon release, the resources are not there several times (once for the application and once for the library).&lt;/p&gt;
&lt;p&gt;Now, every new style-file is added into this ItemGroup.&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary:&lt;/h3&gt;
&lt;p&gt;Using the above, i was able to load my Styles in app.xaml (as you&amp;rsquo;d usually do with a wpf-project) - but doing this for the assembly (without creating a fake executable or so).&lt;/p&gt;
&lt;p&gt;The solution may not be perfect, however it prooved to be quite useful to our designers which had to modify some styles.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>hello world</title>
      <link>https://blog.xmatthias.com/post/hello-world/</link>
      <pubDate>Sun, 03 Sep 2017 11:30:00 +0000</pubDate>
      
      <guid>https://blog.xmatthias.com/post/hello-world/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve been thinking long about starting a blog and finally decided to just try and start one.&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t promise I&amp;rsquo;ll be posting regularily - however I&amp;rsquo;ll try to post whenever i have something new or exciting to write about.&lt;/p&gt;
&lt;p&gt;Most of my interrests are around tech, so the content will be mostly tech.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll see where this brings me.&lt;/p&gt;
&lt;p&gt;so long,
Matthias&lt;/p&gt;
</description>
      
    </item>
    
  </channel>
</rss>
