<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="4.3.3">Jekyll</generator><link href="https://odarriba.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://odarriba.dev/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2026-02-08T19:31:08+01:00</updated><id>https://odarriba.dev/feed.xml</id><title type="html">Óscar de Arriba - odarriba.dev</title><subtitle>Learnings, thoughts and experiments from an Elixir software developer that also enjoys sysadmin and clouds.</subtitle><author><name>Óscar de Arriba</name></author><entry><title type="html">Sending notifications in Elixir with Ravenx</title><link href="https://odarriba.dev/sending-notifications-in-elixir-with-ravenx/" rel="alternate" type="text/html" title="Sending notifications in Elixir with Ravenx" /><published>2017-04-25T18:45:20+02:00</published><updated>2017-04-25T18:45:20+02:00</updated><id>https://odarriba.dev/sending-notifications-in-elixir-with-ravenx</id><content type="html" xml:base="https://odarriba.dev/sending-notifications-in-elixir-with-ravenx/"><![CDATA[<p>During the development of the new version of <a href="http://www.acutar.io/">Acutario</a> in Elixir, we had some issues related to notification dispatching.</p>

<p>One of the improvements we are working on is the possibility of sending notifications to multiple services, like e-mail, Slack, push notifications to mobile apps…</p>

<p>That functionality make us face with the problem of using different strategies depending on a concrete scenario that can be different for each user we want to notify, so we decided to develop a library that help us to manage all that cases. <strong>And we called it <a href="https://github.com/acutario/ravenx">Ravenx</a>.</strong></p>

<h2 id="how-ravenx-works">How Ravenx works</h2>

<p>The library is made of <strong>strategies</strong>, which define a way of sending a notification (Slack, e-mail, APNS, etc), and they have an <a href="https://github.com/acutario/ravenx/blob/master/lib/ravenx/strategy_behaviour.ex">standard interface</a>, so its internal behaviour is abstracted from the outside.</p>

<p>Currently, Ravenx has two different strategies:</p>

<ul>
  <li><strong>Slack</strong>: provides sending slack messages using webhooks URLs.</li>
  <li><strong>E-mail</strong>: provides sending emails using different strategies (the ones included in <a href="https://github.com/thoughtbot/bamboo">bamboo</a>).</li>
</ul>

<p>But, as we are going to see at the end of this article, new strategies can be easily implemented to manage sending notifications to other systems and platforms.</p>

<p>Also, there are several ways of defining <strong>configurations</strong> which the strategies will use to know how to send the notification.</p>

<p>Configurations are per strategy, so they defines how a notification is sent (for example, Mailgun’s configuration to send e-mails).</p>

<h2 id="global-configuration">Global configuration</h2>

<p>This approach includes two kinds of configuration:</p>

<ul>
  <li><strong>General Ravenx configuration:</strong> like the custom strategies to use, or the configuration module of our app (we will see this two aspects in a few moments).</li>
  <li><strong>Per-strategy configuration:</strong> <em>strategy-specific</em> configuration (Mailgun’s config, Slack’s webhook URL…)</li>
</ul>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">config</span> <span class="ss">:ravenx</span><span class="p">,</span> <span class="ss">:slack</span><span class="p">,</span>
  <span class="ss">url:</span> <span class="s2">"..."</span><span class="p">,</span>
  <span class="ss">icon:</span> <span class="s2">":bird:"</span>
</code></pre></div></div>

<h2 id="configuration-module">Configuration module</h2>

<p>A module that have a function for each strategy that receives the payload and returns a map with configurations that apply to that specific payload.</p>

<p>These configuration modules are useful to automatise the configuration generation, for example, if we need to retrieve the slack username of each user in each notification.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">config</span> <span class="ss">:ravenx</span><span class="p">,</span>
  <span class="ss">config:</span> <span class="no">YourApp</span><span class="o">.</span><span class="no">RavenxConfig</span>
</code></pre></div></div>
<p> </p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">YourApp</span><span class="o">.</span><span class="no">RavenxConfig</span> <span class="k">do</span>
  <span class="k">def</span> <span class="n">slack</span> <span class="p">(</span><span class="n">_payload</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">%{</span>
      <span class="ss">url:</span> <span class="s2">"..."</span><span class="p">,</span>
      <span class="ss">icon:</span> <span class="s2">":bird:"</span>
    <span class="p">}</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<h2 id="particular-configuration">Particular configuration</h2>
<p>This is a configuration map sent when a notification is dispatched. Useful to add configuration generated right before sending the notification.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Ravenx</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="n">strategy</span><span class="p">,</span> <span class="n">payload</span><span class="p">,</span> <span class="p">%{</span><span class="ss">url:</span> <span class="s2">"..."</span><span class="p">,</span> <span class="ss">icon:</span> <span class="s2">":bird:"</span><span class="p">})</span>
</code></pre></div></div>

<h2 id="mixing-configurations">Mixing configurations</h2>
<p>For a given notification dispatch we can have configurations of the three kinds. In that case, configurations are merged with this priorities:</p>

<blockquote>
  <p>Global &lt; Module &lt; Particular</p>
</blockquote>

<p>So a particular configuration key is used even if it’s defined in the configuration returned by a configuration module or by the app configuration.</p>

<h2 id="sending-a-notification">Sending a notification</h2>

<p><strong>Ravenx</strong> allows to send a notification in a <strong>synchronous or asynchronous</strong> way. In case you want to send a notification in an asynchronous way, a Task will be launched to perform the operation under the hood.</p>

<p>To send a notification, the only action needed is a call to the library:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Ravenx</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="ss">:slack</span><span class="p">,</span> <span class="p">%{</span><span class="ss">title:</span> <span class="s2">"Hello world!"</span><span class="p">,</span> <span class="ss">body:</span> <span class="s2">"Science is cool"</span><span class="p">})</span>
<span class="c1"># =&gt; {:ok, "ok"}</span>

<span class="no">Ravenx</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="ss">:wadus</span><span class="p">,</span> <span class="p">%{</span><span class="ss">title:</span> <span class="s2">"Hello world!"</span><span class="p">,</span> <span class="ss">body:</span> <span class="s2">"Science is cool"</span><span class="p">})</span>
<span class="c1"># =&gt; {:error, {:unknown_strategy, :wadus}}</span>

<span class="p">{</span><span class="n">status</span><span class="p">,</span> <span class="n">task</span><span class="p">}</span> <span class="o">=</span> <span class="no">Ravenx</span><span class="o">.</span><span class="n">dispatch_async</span><span class="p">(</span><span class="ss">:slack</span><span class="p">,</span> <span class="p">%{</span><span class="ss">title:</span> <span class="s2">"Hello world!"</span><span class="p">,</span> <span class="ss">body:</span> <span class="s2">"Science is cool"</span><span class="p">})</span>
<span class="c1"># =&gt; {:ok, %Task{owner: #PID&lt;0.165.0&gt;, pid: #PID&lt;0.183.0&gt;, ref: #Reference&lt;0.0.4.418&gt;}}</span>

<span class="no">Task</span><span class="o">.</span><span class="n">await</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
<span class="c1"># =&gt; {:ok, "ok"}</span>

<span class="no">Ravenx</span><span class="o">.</span><span class="n">dispatch_async</span><span class="p">(</span><span class="ss">:wadus</span><span class="p">,</span> <span class="p">%{</span><span class="ss">title:</span> <span class="s2">"Hello world!"</span><span class="p">,</span> <span class="ss">body:</span> <span class="s2">"Science is cool"</span><span class="p">})</span>
<span class="c1"># =&gt; {:error, {:unknown_strategy, :wadus}}</span>
</code></pre></div></div>

<h2 id="sending-multiple-notifications">Sending multiple notifications</h2>

<p>Sending a standalone notification is cool, but no one needs another library for that. <strong>The true functionality in Ravenx is sending a notification using multiple strategies in an easy way.</strong></p>

<p>To do that, the library defines a macro that can be used to generate <strong>notification modules</strong>, which can be used to define how to send a particular notification using multiple strategies.</p>

<p>That modules must define a function called <code class="language-plaintext highlighter-rouge">get_notifications_config</code> that receives an object and returns a Keyword list with information of which strategies and which payloads will be used:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">YourApp</span><span class="o">.</span><span class="no">Notification</span><span class="o">.</span><span class="no">NotifyUser</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="c1"># =&gt; [</span>
<span class="c1">#   slack: {:ok, ...},</span>
<span class="c1">#   email_user: {:ok, ...},</span>
<span class="c1">#   email_company: {:ok, ...},</span>
<span class="c1">#   other_notification: {:error, {:unknown_strategy, :invalid_strategy}}</span>
<span class="c1"># ]</span>

<span class="no">YourApp</span><span class="o">.</span><span class="no">Notification</span><span class="o">.</span><span class="no">NotifyUser</span><span class="o">.</span><span class="n">dispatch_async</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="c1"># =&gt; [</span>
<span class="c1">#   slack: {:ok, %Task{..}},</span>
<span class="c1">#   email_user: {:ok, %Task{..}},</span>
<span class="c1">#   email_company: {:ok, %Task{..}},</span>
<span class="c1">#   other_notification: {:error, {:unknown_strategy, :invalid_strategy}}</span>
<span class="c1"># ]</span>
</code></pre></div></div>
<p> </p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">YourApp</span><span class="o">.</span><span class="no">Notification</span><span class="o">.</span><span class="no">NotifyUser</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">Ravenx</span><span class="o">.</span><span class="no">Notification</span>

  <span class="k">def</span> <span class="n">get_notifications_config</span><span class="p">(</span><span class="n">user</span><span class="p">)</span> <span class="k">do</span>
    <span class="c1"># In this function you can generate your payloads and decid which strategies you</span>
    <span class="c1"># want to use depending on the obejct received, and return something like:</span>
    <span class="p">[</span>
      <span class="ss">slack:</span> <span class="p">{</span><span class="ss">:slack</span><span class="p">,</span> <span class="p">%{</span><span class="ss">title:</span> <span class="s2">"Important notification!"</span><span class="p">,</span> <span class="ss">body:</span> <span class="s2">"Wait..."</span><span class="p">},</span> <span class="p">%{</span><span class="ss">channel:</span> <span class="n">user</span><span class="o">.</span><span class="n">slack_username</span><span class="p">}},</span>
      <span class="ss">email_user:</span> <span class="p">{</span><span class="ss">:email</span><span class="p">,</span> <span class="p">%{</span><span class="ss">subject:</span> <span class="s2">"Important notification!"</span><span class="p">,</span> <span class="ss">html_body:</span> <span class="s2">"&lt;h1&gt;Wait...&lt;/h1&gt;"</span><span class="p">,</span> <span class="ss">to:</span> <span class="n">user</span><span class="o">.</span><span class="n">email_address</span><span class="p">}},</span>
      <span class="ss">email_company:</span> <span class="p">{</span><span class="ss">:email</span><span class="p">,</span> <span class="p">%{</span><span class="ss">subject:</span> <span class="s2">"Important notification about an user!"</span><span class="p">,</span> <span class="ss">html_body:</span> <span class="s2">"&lt;h1&gt;Wait...&lt;/h1&gt;"</span><span class="p">,</span> <span class="ss">to:</span> <span class="n">user</span><span class="o">.</span><span class="n">company</span><span class="o">.</span><span class="n">email_address</span><span class="p">}},</span>
      <span class="ss">other_notification:</span> <span class="p">{</span><span class="ss">:invalid_strategy</span><span class="p">,</span> <span class="p">%{</span><span class="ss">text:</span> <span class="s2">"Important notification!"</span><span class="p">},</span> <span class="p">%{</span><span class="ss">option1:</span> <span class="n">value2</span><span class="p">}},</span>
    <span class="p">]</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>So that allows to define all the logic behind a notification generation in a particular module.</p>

<p>That modules can be used (as seen above) to dispatch the notifications in both synchronous and asynchronous way, as when we dispatched simple notifications.</p>

<h2 id="custom-strategies">Custom strategies</h2>

<p>Anyone can create custom strategies and integrate them with Ravenx. To do that, the only requirement is to implement the interface needed and tell Ravenx which modules should use as strategies:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">config</span> <span class="ss">:ravenx</span><span class="p">,</span>
  <span class="ss">strategies:</span> <span class="p">[</span>
    <span class="ss">my_strategy:</span> <span class="no">YourApp</span><span class="o">.</span><span class="no">MyStrategy</span>
  <span class="p">]</span>
</code></pre></div></div>
<p> </p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">YourApp</span><span class="o">.</span><span class="no">MyStrategy</span> <span class="k">do</span>
  <span class="nv">@behaviour</span> <span class="no">Ravenx</span><span class="o">.</span><span class="no">StrategyBehaviour</span>

  <span class="k">def</span> <span class="n">call</span><span class="p">(</span><span class="n">payload</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span> <span class="k">do</span>
    <span class="c1"># ... do stuff ...</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<h2 id="what-ravenx-doesnt-do">What Ravenx doesn’t do</h2>

<p><strong>Ravenx doesn’t take care of dispatching schedule</strong> (limiting the amount of notifications sent simultaneously). As Erlang VM can virtually take care of a lot (<em>really, a lot</em>) of internal processes, this is not a real issue.</p>

<p>You can send a lot of notifications asynchronously and the Erlang VM will be able to manage them without much problem.</p>

<h2 id="wrapping-up">Wrapping up</h2>

<p>Ravenx is not the perfect solution for all the notification scenarios (and it is not intended to be that), but in <a href="http://www.acutar.io/">Acutario</a> we think this can solve some complex scenarios in which you can have to deal with changing configurations, multiple strategies and massive dispatches of notifications.</p>

<p>Using notification modules alongside with the configuration options, the code related to notifications can be organised and reused, avoiding repetitions in multiple places of your code.</p>

<p><strong>If you have any question about Ravenx</strong>, you can read its <a href="https://hexdocs.pm/ravenx/">documentation</a> here, ask any question here or just <a href="https://github.com/acutario/ravenx">open an issue</a>! (Pull requests are welcome too :)</p>

<p>Hope you enjoyed this article and see you soon (in ElixirConf.EU if you assist!)</p>]]></content><author><name>Óscar de Arriba</name></author><category term="notifications" /><category term="libraries" /><category term="elixir" /><summary type="html"><![CDATA[During the development of the new version of Acutario in Elixir, we had some issues related to notification dispatching.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://odarriba.dev/sending-notifications-in-elixir-with-ravenx/image.webp" /><media:content medium="image" url="https://odarriba.dev/sending-notifications-in-elixir-with-ravenx/image.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Integrating CircleCI with Elixir/Phoenix</title><link href="https://odarriba.dev/integrating-circle-ci-with-elixir-phoenix/" rel="alternate" type="text/html" title="Integrating CircleCI with Elixir/Phoenix" /><published>2016-08-12T10:29:20+02:00</published><updated>2016-08-12T10:29:20+02:00</updated><id>https://odarriba.dev/integrating-circle-ci-with-elixir-phoenix</id><content type="html" xml:base="https://odarriba.dev/integrating-circle-ci-with-elixir-phoenix/"><![CDATA[<p>Having automated tests in a repository can be considered a <em>must-do</em> in any kind of project. In Elixir/Phoenix we can create complex and maintainable tests in a short time but, how can we integrate it with CircleCI?</p>

<h2 id="getting-in-touch-with-circleci">Getting in touch with CircleCI</h2>

<p><a href="https://circleci.com">CircleCI</a> is just another continuous integration platform, free for both public and private repositories.</p>

<p>The main advantage is that, as it’s based on top of containers, you can can access via SSH to the container where your tests are running and debug environment/build issues easily.</p>

<h2 id="so-whats-the-matter-with-elixir-in-circleci">So, what’s the matter with Elixir in CircleCI?</h2>

<p><strong>CircleCI doesn’t have native support for Elixir/Phoenix projects</strong>, so the only option left is trying to automatise the installation of the environment needed to run the tests.</p>

<p>This shouldn’t be a real trouble since they allow you to define the shell commands executed at each step, so the process can be customised as much as you want.</p>

<p>In my case, I have decided to install the environment using <a href="https://github.com/asdf-vm/asdf">ASDF</a>, a new lightweight version manager that can handle multiple languages/platforms using plugins.</p>

<p>The idea is to install it (if it’s not previously installed) and apply the plugins needed. Then, we can use <code class="language-plaintext highlighter-rouge">.tool_versions</code> file (the default one used by ASDF) to install required dependencies and use them to run the actual tests.</p>

<p>So here is the circle.yml that does it:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">machine</span><span class="pi">:</span>
  <span class="na">environment</span><span class="pi">:</span>
    <span class="na">PATH</span><span class="pi">:</span> <span class="s2">"</span><span class="s">$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"</span>
    <span class="na">MIX_ENV</span><span class="pi">:</span> <span class="s2">"</span><span class="s">test"</span>
<span class="na">dependencies</span><span class="pi">:</span>
  <span class="na">cache_directories</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">~/.asdf</span>
  <span class="na">pre</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">if ! asdf | grep version; then git clone https://github.com/HashNuke/asdf.git ~/.asdf; fi</span>
    <span class="pi">-</span> <span class="s">if ! asdf plugin-list | grep erlang; then asdf plugin-add erlang https://github.com/HashNuke/asdf-erlang.git; fi</span>
    <span class="pi">-</span> <span class="s">if ! asdf plugin-list | grep elixir; then asdf plugin-add elixir https://github.com/HashNuke/asdf-elixir.git; fi</span>
    <span class="pi">-</span> <span class="s">asdf plugin-update erlang</span>
    <span class="pi">-</span> <span class="s">asdf plugin-update elixir</span>
    <span class="pi">-</span> <span class="s">asdf install</span>
    <span class="pi">-</span> <span class="s">cp config/test.ci.exs config/test.exs</span>
    <span class="pi">-</span> <span class="s">yes | mix deps.get</span>
    <span class="pi">-</span> <span class="s">yes | mix local.rebar</span>
<span class="na">database</span><span class="pi">:</span>
  <span class="na">override</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">mix ecto.drop</span>
    <span class="pi">-</span> <span class="s">mix ecto.create</span>
    <span class="pi">-</span> <span class="s">mix ecto.migrate</span>
<span class="na">test</span><span class="pi">:</span>
  <span class="na">override</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">mix test</span>
<span class="na">experimental</span><span class="pi">:</span>
  <span class="na">notify</span><span class="pi">:</span>
    <span class="na">branches</span><span class="pi">:</span>
      <span class="na">only</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">master</span>
</code></pre></div></div>

<p>Also, some adjustments are made:</p>

<ul>
  <li>Various environment variables, like the <code class="language-plaintext highlighter-rouge">$PATH</code> including ASDF paths</li>
  <li>Copying CircleCI specific project config to use it on tests</li>
  <li>Install required dependencies</li>
  <li>Clean the database</li>
  <li>Only notify the builds on master branch (to avoid flooding of notifications on <em>non-master</em> commits).</li>
</ul>

<p>Note that, by adding ASDF directory to the cache list, we can avoid reinstalling and rebuilding Erlang and Elixir, which will take (<em>really</em>) long time on first execution.</p>

<h2 id="benchmarking">Benchmarking</h2>

<p>Thanks to the cache between builds, the build times of one of the projects we use at work are:</p>

<ul>
  <li>~3 minutes on regular builds.</li>
  <li>~13 minutes on the first build (download and build Erlang &amp; Elixir).</li>
</ul>]]></content><author><name>Óscar de Arriba</name></author><category term="devops" /><category term="elixir" /><summary type="html"><![CDATA[Having automated tests in a repository can be considered a must-do in any kind of project. In Elixir/Phoenix we can create complex and maintainable tests in a short time but, how can we integrate it with CircleCI?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://odarriba.dev/integrating-circle-ci-with-elixir-phoenix/cicle-ci-phoenix.webp" /><media:content medium="image" url="https://odarriba.dev/integrating-circle-ci-with-elixir-phoenix/cicle-ci-phoenix.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Installing OpenVPN Server</title><link href="https://odarriba.dev/installing-openvpn-server/" rel="alternate" type="text/html" title="Installing OpenVPN Server" /><published>2015-10-04T17:45:20+02:00</published><updated>2015-10-04T17:45:20+02:00</updated><id>https://odarriba.dev/installing-openvpn-server</id><content type="html" xml:base="https://odarriba.dev/installing-openvpn-server/"><![CDATA[<p>Today I’ve been installing <strong>OpenVPN server</strong> on my home server to being able to securely connect to my local network from anywhere. This can allow you to:</p>

<ul>
  <li>Having access to local services on your local network , like a (in my case) a <a href="https://github.com/odarriba/docker-timemachine">Time Machine docker</a> service.</li>
  <li>Access services only available from your country IP when travelling to other places.</li>
  <li>Being able to use open hotspots while encrypting your whole network traffic.</li>
</ul>

<p>In order to get it, my first thought was to install the server on the bare metal machine (not on a <em>Docker</em> container) because it may require some network privileges that can make it unable to work behind the <em>Docker</em> network layer.</p>

<p>But searching a bit over the Internet I’ve found <a href="https://github.com/kylemanna/docker-openvpn">this repository</a> that includes a functional Docker image. It doesn’t just works, but it includes a full documentation file with instructions to set the server up in two different containers (the one that has the daemon running and the one that stores the secure data).</p>

<p><strong>So, in less that 5 minutes my OpenVPN server was up and running!</strong> Also I have generated the CA file and the client certificates, so I can connect from anywhere like being at home.</p>

<h2 id="clients">Clients</h2>

<p>In Mac OSX (10.11 — El Capitán) I installed <a href="https://tunnelblick.net/">Tunnelblick</a>, a free and open source alternative to OpenVPN client or Viscoso.app. It has an easy and lightweight GUI, perfect to avoid resource consumption and annoyance while using it.</p>

<p>In Windows 10 I used the official OpenVPN client, but it doesn’t work <em>out-of-the-box</em>. To make it work, <strong>its executables should be marked to be run with administrator privileges</strong>, so they can add the networking routes needed to route the traffic through the VPN.</p>]]></content><author><name>Óscar de Arriba</name></author><category term="sysadmin" /><summary type="html"><![CDATA[Today I’ve been installing OpenVPN server on my home server to being able to securely connect to my local network from anywhere. This can allow you to:]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://odarriba.dev/installing-openvpn-server/image.webp" /><media:content medium="image" url="https://odarriba.dev/installing-openvpn-server/image.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>