<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Random Ramblings</title><link href="https://copyninja.in/" rel="alternate"/><link href="https://copyninja.in/feeds/all.atom.xml" rel="self"/><id>https://copyninja.in/</id><updated>2026-04-12T12:53:00+05:30</updated><subtitle>Random thoughts shooting out of volatile mind</subtitle><entry><title>Hardening the Unpacakgeable: A systemd-run Sandbox for Third-Party Binaries</title><link href="https://copyninja.in/blog/safe-run-binary-sandbox.html" rel="alternate"/><published>2026-04-12T12:53:00+05:30</published><updated>2026-04-12T12:53:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2026-04-12:/blog/safe-run-binary-sandbox.html</id><summary type="html">&lt;p class="first last"&gt;A technical deep-dive into sandboxing untrusted npm and Python
binaries using systemd-run and Linux namespaces.&lt;/p&gt;
</summary><content type="html">&lt;div class="section" id="the-shift-in-software-consumption"&gt;
&lt;h2&gt;The Shift in Software Consumption&lt;/h2&gt;
&lt;p&gt;Historically, I have been a &amp;quot;distribution-first&amp;quot; user. Sticking to tools
packaged within the Debian archives provides a layer of trust; maintainers
validate licenses, audit code, and ensure the entire dependency chain is
verified. However, the rapid pace of development in the Generative AI
space—specifically with new tools like Gemini-CLI—has made this traditional
approach difficult to sustain.&lt;/p&gt;
&lt;p&gt;Many modern CLI tools are built within the &lt;strong&gt;npm&lt;/strong&gt; or &lt;strong&gt;Python&lt;/strong&gt; ecosystems. For
a distribution packager, these are a nightmare; packaging a single tool often
requires packaging a massive, shifting dependency chain. Consequently, I found
myself forced to use third-party binaries, bypassing the safety of the Debian
archive.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-supply-chain-risk"&gt;
&lt;h2&gt;The Supply Chain Risk&lt;/h2&gt;
&lt;p&gt;Recent supply chain attacks affecting widely used packages like &lt;tt class="docutils literal"&gt;axios&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;LiteLLM&lt;/tt&gt; have made it clear: running unvetted binaries on a personal system
is a significant risk. These scripts often have full access to your &lt;tt class="docutils literal"&gt;$HOME&lt;/tt&gt;
directory, SSH keys, and the system D-Bus.&lt;/p&gt;
&lt;p&gt;After discussing these concerns with a colleague, I was inspired by his
approach—using a Flatpak-style sandbox for even basic applications like Google
Chrome. I decided to build a generalized version of this using &lt;strong&gt;OpenCode&lt;/strong&gt; and
&lt;strong&gt;Qwen 3.6 Fast&lt;/strong&gt; (which was available for free use at the time) to create a
robust, transient sandbox utility.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-solution-safe-run-binary"&gt;
&lt;h2&gt;The Solution: safe-run-binary&lt;/h2&gt;
&lt;p&gt;My script, &lt;a class="reference external" href="https://github.com/copyninja/dotfiles/blob/master/bin/safe-run-binary"&gt;safe-run-binary&lt;/a&gt;,
leverages &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-run&lt;/span&gt;&lt;/tt&gt; to execute binaries within an isolated scope. It
implements strict filesystem masking and resource control to ensure that even if
a dependency is compromised, the &amp;quot;blast radius&amp;quot; is contained.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="key-technical-features"&gt;
&lt;h2&gt;Key Technical Features&lt;/h2&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;strong&gt;1. Virtualized Home Directory (tmpfs)&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;Instead of exposing my real home directory, the script mounts a &lt;tt class="docutils literal"&gt;tmpfs&lt;/tt&gt;
over &lt;tt class="docutils literal"&gt;$HOME&lt;/tt&gt;. It then selectively creates and bind-mounts only the
necessary subdirectories (like &lt;tt class="docutils literal"&gt;.cache&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;.config&lt;/tt&gt;) into a virtual
structure. This prevents the application from ever &amp;quot;seeing&amp;quot; sensitive files
like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.ssh&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.gnupg&lt;/span&gt;&lt;/tt&gt;.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;2. D-Bus Isolation via xdg-dbus-proxy&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;For GUI applications, providing raw access to the D-Bus is a security hole.
The script uses &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;xdg-dbus-proxy&lt;/span&gt;&lt;/tt&gt; to sit between the application and the
system bus. By using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--filter&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--talk=org.freedesktop.portal.*&lt;/span&gt;&lt;/tt&gt;
flags, the app can only communicate with necessary portals (like the file
picker) rather than sniffing the entire bus.&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;3. Linux Namespace Restrictions&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p class="first"&gt;The sandbox utilizes several &lt;tt class="docutils literal"&gt;systemd&lt;/tt&gt; execution properties to harden the
process:&lt;/p&gt;
&lt;ul class="last simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;RestrictNamespaces=yes&lt;/tt&gt;: For CLI tools, this prevents the app from
creating its own nested namespaces.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;PrivateTmp=yes&lt;/tt&gt;: Ensures a private &lt;tt class="docutils literal"&gt;/tmp&lt;/tt&gt; space that isn't shared with
the host.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;NoNewPrivileges=yes&lt;/tt&gt;: Prevents the binary from gaining elevated
permissions through SUID/SGID bits.&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;4. GPU and Audio Passthrough&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;The script intelligently detects and binds Wayland, PipeWire, and NVIDIA/DRI
device nodes. This allows browsers like Firefox to run with full hardware
acceleration and audio support while remaining locked out of the rest of the
filesystem.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="section" id="usage"&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;To run a CLI tool like Gemini-CLI with access only to a specific directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;safe-run-binary&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;~/.gemini-config&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;npx&lt;span class="w"&gt; &lt;/span&gt;@google/gemini-cli
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For a GUI application like Firefox:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;safe-run-binary&lt;span class="w"&gt; &lt;/span&gt;--gui&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;~/.mozilla&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;~/.cache/mozilla&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;~/Downloads&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;firefox
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;While it is not always possible to escape the need for third-party software, it
is possible to control the environment in which it operates. By leveraging
native Linux primitives like &lt;tt class="docutils literal"&gt;systemd&lt;/tt&gt; and namespaces, high-grade isolation is
achievable.&lt;/p&gt;
&lt;p&gt;PS: &lt;em&gt;If you spot any issues or have suggestions for improving the script, feel free
to raise a PR on the&lt;/em&gt; &lt;a class="reference external" href="https://github.com/copyninja/dotfiles/"&gt;repo&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="sandbox"/><category term="debian"/><category term="security"/><category term="systemd"/><category term="npm"/></entry><entry><title>Using Gemini CLI to Configure the Hyprland Window Manager</title><link href="https://copyninja.in/blog/agentic_hyprland_config.html" rel="alternate"/><published>2026-03-15T12:35:00+05:30</published><updated>2026-03-15T12:35:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2026-03-15:/blog/agentic_hyprland_config.html</id><summary type="html">&lt;p class="first last"&gt;A guide on migrating to the Hyprland window manager using the Gemini
CLI to automate configuration and reduce system bloat.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;What led to this experiment? Well, for one, Well, for one, there was a thought
shared by Andrej Karpathy regarding the shift towards &amp;quot;Agentic&amp;quot; workflows.&lt;/p&gt;
&lt;blockquote class="epigraph"&gt;
&lt;p&gt;&amp;quot;The future of software is not just 'tools', but 'agents' that can navigate
complex tasks on your behalf.&amp;quot;&lt;/p&gt;
&lt;p class="attribution"&gt;&amp;mdash;&lt;a class="reference external" href="https://twitter.com/karpathy/status/2026731645169185220"&gt;Andrej Karpathy&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Recently, I spoke with &lt;a class="reference external" href="https://researchut.com/"&gt;Ritesh&lt;/a&gt;, who mentioned his
success using the Gemini CLI to debug an idle power drain issue on his laptop. I
wanted to experiment with this myself, and I had the perfect use case:
configuring the Hyprland Window Manager on my aging laptop.&lt;/p&gt;
&lt;p&gt;The machine is nearly eight years old with 12GB of RAM (upgraded from the
original 4GB). I found that GNOME and KDE were becoming overkill, often leading
to system freezes when running multiple AI-powered IDEs like Antigravity and VS
Code with Co-pilot. Coincidentally, I noticed my Jio number had a &amp;quot;Google One
2TB&amp;quot; and &amp;quot;Google AI Premium&amp;quot; plan available to claim. I claimed it, and now here
I am, experimenting with the Gemini CLI.&lt;/p&gt;
&lt;div class="section" id="getting-started"&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;First, you need to install &lt;tt class="docutils literal"&gt;geminicli&lt;/tt&gt;. It is an open-source project, and
currently, the easiest way to install it is via the Node Package Manager (npm):&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
npm&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;&amp;#64;google/gemini-cli
&lt;/pre&gt;
&lt;p&gt;Next, we need to create a context for Gemini—a set of instructions for it to
follow throughout the project. This is managed via a &lt;tt class="docutils literal"&gt;GEMINI.md&lt;/tt&gt; file. I went
to Google Gemini, explained my requirements, and asked it to generate one for
me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My requirements were:&lt;/strong&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;A minimalist but fully functional session, comparable to my existing GNOME
setup.&lt;/li&gt;
&lt;li&gt;Basic functionalities including wallpaper, screen locks, and a status bar
with system icons.&lt;/li&gt;
&lt;li&gt;Swapping Control and Caps Lock (a must for Emacs users).&lt;/li&gt;
&lt;li&gt;Mandatory permission prompts for privileged operations; otherwise, it can
work freely within a specified directory.&lt;/li&gt;
&lt;li&gt;Persistent memory/artifacts for the session.&lt;/li&gt;
&lt;li&gt;Permission to inspect my current session to understand the existing hardware
and software configuration.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The goal was to reduce bloat and reclaim memory for heavy applications like
Antigravity and VS Code. Gemini provided the following &lt;tt class="docutils literal"&gt;GEMINI.md&lt;/tt&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gh"&gt;# Role: Hyprland Configuration Specialist (Minimalist &amp;amp; High-Performance)&lt;/span&gt;

You are a Linux Systems Engineer specializing in migrating users from heavy
Desktop Environments to minimalist, tiling-based Wayland sessions on Debian.
Your goal is to maximize available RAM for heavy applications while maintaining
essential desktop features.

&lt;span class="gu"&gt;## 1. Environment &amp;amp; Persona&lt;/span&gt;
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Target OS:**&lt;/span&gt; Debian (Linux)
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Target WM:**&lt;/span&gt; Hyprland
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Hardware:**&lt;/span&gt; ThinkPad E470 (i5-7th Gen, 12GB RAM)
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**User Profile:**&lt;/span&gt; Emacs user, prioritizes &amp;quot;anti-gravity&amp;quot; (zero bloat).
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Tone:**&lt;/span&gt; Technical, concise, and security-conscious.

&lt;span class="gu"&gt;## 2. Core Functional Requirements&lt;/span&gt;
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Status Bar:**&lt;/span&gt; &lt;span class="sb"&gt;`waybar`&lt;/span&gt; (with CPU, RAM, Network, and Battery icons).
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Wallpaper:**&lt;/span&gt; &lt;span class="sb"&gt;`swww`&lt;/span&gt; or &lt;span class="sb"&gt;`hyprpaper`&lt;/span&gt;.
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Screen Lock:**&lt;/span&gt; &lt;span class="sb"&gt;`hyprlock`&lt;/span&gt; + &lt;span class="sb"&gt;`hypridle`&lt;/span&gt;.
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Input Mapping:**&lt;/span&gt; Swap Control and Caps Lock (&lt;span class="sb"&gt;`kb_options = ctrl:nocaps`&lt;/span&gt;).

&lt;span class="gu"&gt;## 3. Operational Constraints&lt;/span&gt;
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Permission First:**&lt;/span&gt; Ask before using &lt;span class="sb"&gt;`sudo`&lt;/span&gt; or writing outside the work directory.
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Inspection:**&lt;/span&gt; Use &lt;span class="sb"&gt;`hyprctl`&lt;/span&gt;, &lt;span class="sb"&gt;`lsmod`&lt;/span&gt;, or &lt;span class="sb"&gt;`gsettings`&lt;/span&gt; for compatibility checks.
&lt;span class="k"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="gs"&gt;**Artifact Management:**&lt;/span&gt; Update &lt;span class="sb"&gt;`MEMORY.md`&lt;/span&gt; after every major step.
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Gemini also recommended creating a &lt;tt class="docutils literal"&gt;MEMORY.md&lt;/tt&gt; file to track progress.
Interestingly, Gemini remembered that I had previously shared &lt;tt class="docutils literal"&gt;dmidecode&lt;/tt&gt;
output, so it already knew my exact laptop specs. (Though it did include a note
about me being a &amp;quot;daily rice eater&amp;quot;—I assume it meant Linux 'ricing,' though I
actually use Debian Unstable, not Stable!).&lt;/p&gt;
&lt;p&gt;The AI suggested starting with this prompt:&lt;/p&gt;
&lt;blockquote&gt;
Read MEMORY.md and GEMINI.md. Based on my hardware, give me a shell script to
inspect my current GNOME environment so we can start replicating the session
basics.&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="how-did-it-go"&gt;
&lt;h2&gt;How Did It Go?&lt;/h2&gt;
&lt;p&gt;I initialized a git repository for these files and instructed the Gemini CLI to
update &lt;tt class="docutils literal"&gt;GEMINI.md&lt;/tt&gt; and commit changes after every major step so I could track
the progress.&lt;/p&gt;
&lt;p&gt;The workflow looked like this:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;strong&gt;Inspection:&lt;/strong&gt; It created a &lt;a class="reference external" href="https://github.com/copyninja/hyprland-config/blob/main/inspect_gnome.sh"&gt;script&lt;/a&gt;
to extract my GNOME settings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration:&lt;/strong&gt; Once I provided the output, it began configuring Hyprland.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Utilities:&lt;/strong&gt; It generated an &lt;a class="reference external" href="https://github.com/copyninja/hyprland-config/blob/main/install_utils.sh"&gt;installation script&lt;/a&gt;
for all required Wayland utilities.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validation:&lt;/strong&gt; All changes were staged in a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;hypr-config-draft&lt;/span&gt;&lt;/tt&gt; folder. I
had Gemini verify them using &lt;tt class="docutils literal"&gt;hyprland &lt;span class="pre"&gt;--verify-config&lt;/span&gt;&lt;/tt&gt; before moving them
to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.config/hypr&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Most things worked immediately, but I hit a snag with the wallpaper. Even after
generating the config, &lt;tt class="docutils literal"&gt;hyprpaper&lt;/tt&gt; failed to display anything. The AI got
stuck in a loop trying to debug it. I eventually spawned a second Gemini CLI
instance to review the code and logs.&lt;/p&gt;
&lt;p&gt;The debug log showed: &lt;tt class="docutils literal"&gt;'DEBUG ]: Monitor &lt;span class="pre"&gt;eDP-1&lt;/span&gt; has no target: no wp will be
created'&lt;/tt&gt;.
It turns out the configuration format was outdated. By feeding the &lt;a class="reference external" href="https://wiki.hypr.land/Hypr-Ecosystem/hyprpaper/"&gt;Hyprpaper
Wiki&lt;/a&gt; into the AI, it
finally corrected the config, and the wallpaper appeared.&lt;/p&gt;
&lt;p&gt;After that, it successfully fixed an &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ssh-agent&lt;/span&gt;&lt;/tt&gt; issue and configured a
clipboard manager with custom keybindings.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="learnings"&gt;
&lt;h2&gt;Learnings&lt;/h2&gt;
&lt;p&gt;I have used window managers for a long time because my hardware was rarely
top-of-the-line. However, I had moved back to KDE/GNOME with the arrival of
Wayland because most of my preferred WMs were X11-based.&lt;/p&gt;
&lt;p&gt;Manually configuring a window manager is a painful, time-consuming process
involving endless wiki-trawling and trial-and-error. What usually takes weeks
took only a few hours with the Gemini CLI.&lt;/p&gt;
&lt;p&gt;AI isn't perfect—I still had to step in and guide it when it hit a wall—but the
efficiency gain is undeniable. If you're interested in the configuration or the
history of the session, you can find the repository &lt;a class="reference external" href="https://github.com/copyninja/hyprland-config"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I still have a few pending items in &lt;tt class="docutils literal"&gt;MEMORY.md&lt;/tt&gt;, but I'll tackle those next
time!&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="gemini cli"/><category term="agentic workflows"/><category term="hyprland"/></entry><entry><title>Learning Notes: Debsecan MCP Server</title><link href="https://copyninja.in/blog/debsecan-mcp.html" rel="alternate"/><published>2026-02-21T17:13:00+05:30</published><updated>2026-02-21T17:13:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2026-02-21:/blog/debsecan-mcp.html</id><summary type="html">&lt;p class="first last"&gt;This post describes a new learning project: an MCP server inspired by
debsecan.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Since Generative AI is currently the most popular topic, I wanted to get my
hands dirty and learn something new. I was learning about the Model Context
Protocol at the time and wanted to apply it to build something simple.&lt;/p&gt;
&lt;div class="section" id="idea"&gt;
&lt;h2&gt;Idea&lt;/h2&gt;
&lt;p&gt;On Debian systems, we use &lt;cite&gt;debsecan&lt;/cite&gt; to find vulnerabilities. However, the tool
currently provides a simple list of vulnerabilities and packages with no
indication of the system's security posture—meaning no criticality information
is exposed and no executive summary is provided regarding what needs to be
fixed. Of course, one can simply run the following to install existing fixes and
be done with it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;debsecan&lt;span class="w"&gt; &lt;/span&gt;--suite&lt;span class="w"&gt; &lt;/span&gt;sid&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="w"&gt; &lt;/span&gt;packages&lt;span class="w"&gt; &lt;/span&gt;--only-fixed&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But this is not how things work in corporate environments; you need to provide a
report showing the system's previous state and the actions taken to bring it to
a safe state. It is all about metrics and reports.&lt;/p&gt;
&lt;p&gt;My goal was to use &lt;cite&gt;debsecan&lt;/cite&gt; to generate a list of vulnerabilities, find more
detailed information on them, and prioritize them as critical, high, medium, or
low. By providing this information to an AI, I could ask it to generate an
executive summary report detailing what needs to be addressed immediately and
the overall security posture of the system.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="initial-take"&gt;
&lt;h2&gt;Initial Take&lt;/h2&gt;
&lt;p&gt;My initial thought was to use an existing LLM, either self-hosted or a
cloud-based LLM like Gemini (which provides an API with generous limits via AI
Studio). I designed functions to output the list of vulnerabilities on the
system and provide detailed information on each. The idea was to use these as
&amp;quot;tools&amp;quot; for the LLM.&lt;/p&gt;
&lt;div class="section" id="learnings"&gt;
&lt;h3&gt;Learnings&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;I learned about open-source LLMs using Ollama, which allows you to download
and use models on your laptop.&lt;/li&gt;
&lt;li&gt;I used Llama 3.1, Llama 3.2, and Granite 4 on my laptop without a GPU. I
managed to run my experiments, even though they were time-consuming and
occasionally caused my laptop to crash.&lt;/li&gt;
&lt;li&gt;I learned about Pydantic and how to use it to parse custom JSON schemas with
minimal effort.&lt;/li&gt;
&lt;li&gt;I learned about osv.dev, an open-source initiative by Google that aggregates
vulnerability information from various sources and provides data in a
well-documented JSON schema format.&lt;/li&gt;
&lt;li&gt;I learned about the EPSS (Exploit Prediction Scoring System) and how it is
used alongside static CVSS scoring to detect truly critical vulnerabilities.
The EPSS score provides an idea of the probability of a vulnerability being
exploited in the wild based on actual real-world attacks.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These experiments led to a collection of &lt;a class="reference external" href="https://github.com/copyninja/notebooks/tree/main/langchain"&gt;notebooks&lt;/a&gt;. One key takeaway
was that when defining tools, I cannot simply output massive amounts of text
because it consumes tokens and increases costs for paid models (though it is
fine for local models using your own hardware and energy). Self-hosted models
require significant prompting to produce proper output, which helped me
understand the real-world application of prompt engineering.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="change-of-plans"&gt;
&lt;h2&gt;Change of Plans&lt;/h2&gt;
&lt;p&gt;Despite extensive experimentation, I felt I was nowhere close to a full
implementation. While using a Gemini learning tool to study MCP, it suddenly
occurred to me: why not write the entire thing as an MCP server? This would save
me from implementing the agent side and allow me to hook it into any
IDE-based LLM.&lt;/p&gt;
&lt;div class="section" id="design"&gt;
&lt;h3&gt;Design&lt;/h3&gt;
&lt;p&gt;This MCP server is primarily a mix of a &amp;quot;tool&amp;quot; (which executes on the server
machine to identify installed packages and their vulnerabilities) and a
&amp;quot;resource&amp;quot; (which exposes read-only information for a specific CVE ID).&lt;/p&gt;
&lt;p&gt;The MCP exposes two tools:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;List Vulnerabilities: This tool identifies vulnerabilities in the packages
installed on the system, categorizes them using CVE and EPSS scores, and
provides a dictionary of critical, high, medium, and low vulnerabilities.&lt;/li&gt;
&lt;li&gt;Research Vulnerabilities: Based on the user prompt, the LLM can identify
relevant vulnerabilities and pass them to this function to retrieve details
such as whether a fix is available, the fixed version, and criticality.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="vibe-coding"&gt;
&lt;h3&gt;Vibe Coding&lt;/h3&gt;
&lt;p&gt;&amp;quot;Vibe coding&amp;quot; is the latest trend, with many claiming that software engineering
jobs are a thing of the past. Without going into too much detail, I decided to
give it a try. While this is not my first &amp;quot;vibe coded&amp;quot; project (I have done this
previously at work using corporate tools), it is my first attempt to vibe code a
hobby/learning project.&lt;/p&gt;
&lt;p&gt;I chose Antigravity because it seemed to be the only editor providing a
sufficient amount of free tokens. For every vibe coding project, I spend time
thinking about the barebones skeleton: the modules, function return values, and
data structures. This allows me to maintain control over the LLM-generated code
so it doesn't become overly complicated or incomprehensible.&lt;/p&gt;
&lt;p&gt;As a first step, I wrote down my initial design in a requirements document. In
that document, I explicitly called for using &lt;a class="reference external" href="https://github.com/copyninja/debsecan-mcp/blob/main/docs/requirement.md"&gt;debsecan&lt;/a&gt; as
the model for various components. Additionally, I asked the AI to reference my
specific &lt;a class="reference external" href="https://github.com/copyninja/notebooks/blob/main/langchain/secscan-common.ipynb"&gt;code for the EPSS logic&lt;/a&gt;.
The reasons were:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;cite&gt;debsecan&lt;/cite&gt; already solves the core problem; I am simply rebuilding it.
&lt;cite&gt;debsecan&lt;/cite&gt; uses a single file generated by the Debian Security team
containing all necessary information, which prevents us from needing multiple
external sources.&lt;/li&gt;
&lt;li&gt;This provides the flexibility to categorize vulnerabilities within the
listing tool itself since all required information is readily available,
unlike my original notebook-based design.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I initially used Gemini 3 Flash as the model because I was concerned about
exceeding my free limits.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="hiccups"&gt;
&lt;h3&gt;Hiccups&lt;/h3&gt;
&lt;p&gt;Although it initially seemed successful, I soon noticed discrepancies between
the local &lt;cite&gt;debsecan&lt;/cite&gt; outputs and the outputs generated by the tools. I asked the
AI to fix this, but after two attempts, it still could not match the outputs. I
realized it was writing its own version-comparison logic and failing
significantly.&lt;/p&gt;
&lt;p&gt;Finally, I instructed it to depend entirely on the &lt;em&gt;python-apt&lt;/em&gt; module for
version comparison; since it is not on PyPI, I asked it to pull directly from
the Git source. This solved some issues, but the problem persisted. By then, my
weekly quota was exhausted, and I stopped debugging.&lt;/p&gt;
&lt;p&gt;A week later, I resumed debugging with the Claude 3.5 Sonnet model. Within 20-25
minutes, it found the fix, which involved &lt;a class="reference external" href="https://github.com/copyninja/debsecan-mcp/commit/4fdf5a2ab139f3c0c335d24973892ddfaf2b08e0#diff-9d3ed702945a5c91f0ed3e54404324fecfca1fbd7ae5fb44508081c6040e9276"&gt;four lines of changes&lt;/a&gt;
in the parsing logic. However, I ran out of limits again before I could proceed
further.&lt;/p&gt;
&lt;p&gt;In the requirements, I specified that the &lt;em&gt;list vulnerabilities&lt;/em&gt; tool should
only provide a dictionary of CVE IDs divided by severity. However, the AI
instead provided full text for all vulnerability details, resulting in excessive
data—including negligible vulnerabilities—being sent to the LLM. Consequently,
it never called the &lt;em&gt;research vulnerabilities&lt;/em&gt; tool. Since I had run out of
limits, I manually fixed this in a &lt;a class="reference external" href="https://github.com/copyninja/debsecan-mcp/commit/32f291d5ec4966b1349d39cfcb5d154e64ad844d"&gt;follow-up commit&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="how-to-use"&gt;
&lt;h2&gt;How to Use&lt;/h2&gt;
&lt;p&gt;I have published the current work in the &lt;a class="reference external" href="https://github.com/copyninja/debsecan-mcp"&gt;debsecan-mcp&lt;/a&gt; repository. I have used the same
license as the original &lt;em&gt;debsecan&lt;/em&gt;. I am not entirely sure how to interpret
licenses for vibe-coded projects, but here we are.&lt;/p&gt;
&lt;p&gt;To use this, you need to install the tool in a virtual environment and configure
your IDE to use the MCP. Here is how I set it up for Visual Studio Code:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Follow the &lt;a class="reference external" href="https://code.visualstudio.com/docs/copilot/customization/mcp-servers#_add-an-mcp-server"&gt;guide from the VS Code documentation&lt;/a&gt;
regarding adding an MCP server.&lt;/li&gt;
&lt;li&gt;My global &lt;cite&gt;mcp.json&lt;/cite&gt; looks like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;servers&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;debsecan-mcp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;command&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;uv&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--directory&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/vasudev/Documents/personal/FOSS/debsecan-mcp/debsecan-mcp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;run&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;debsecan-mcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;inputs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;I am running it directly from my local codebase using a virtualenv created
with &lt;em&gt;uv&lt;/em&gt;. You may need to tweak the path based on your installation.&lt;/li&gt;
&lt;li&gt;To use the MCP server in the Copilot chat window, reference it using
&lt;cite&gt;#debsecan-mcp&lt;/cite&gt;. The LLM will then use the server for the query.&lt;/li&gt;
&lt;li&gt;Use a prompt like: &lt;em&gt;&amp;quot;Give an executive summary of the system security status
and immediate actions to be taken.&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;You can observe the LLM using &lt;cite&gt;list_vulnerabilities&lt;/cite&gt; followed by
&lt;cite&gt;research_cves&lt;/cite&gt;. Because the first tool only provides CVE IDs based on
severity, the LLM is smart enough to research only high and critical
vulnerabilities, thereby saving tokens.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="what-s-next"&gt;
&lt;h2&gt;What's Next?&lt;/h2&gt;
&lt;p&gt;This MCP is not yet perfect and has the following issues:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The &lt;cite&gt;list_vulnerabilities&lt;/cite&gt; dictionary contains duplicate CVE IDs because the
code used a list instead of a set. While the LLM is smart enough to
deduplicate these, it still costs extra tokens.&lt;/li&gt;
&lt;li&gt;Because I initially modeled this on &lt;cite&gt;debsecan&lt;/cite&gt;, it uses a raw method for
parsing &lt;cite&gt;/var/lib/dpkg/status&lt;/cite&gt; instead of &lt;cite&gt;python-apt&lt;/cite&gt;. I am considering
switching to &lt;cite&gt;python-apt&lt;/cite&gt; to reduce maintenance overhead.&lt;/li&gt;
&lt;li&gt;Interestingly, the AI did not add a single unit test, which is disappointing.
I will add these once my limits are restored.&lt;/li&gt;
&lt;li&gt;I need to create a cleaner README with usage instructions.&lt;/li&gt;
&lt;li&gt;I need to determine if the MCP can be used via HTTP as well as stdio.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Vibe coding is interesting, but things can get out of hand if not managed
properly. Even with a good process, code must be reviewed and tested; you cannot
blindly trust an AI to handle everything. Even if it adds tests, you must
validate them, or you are doomed!&lt;/p&gt;
&lt;/div&gt;
</content><category term="development"/><category term="generative_ai"/><category term="debsecan"/><category term="mcp"/><category term="llm"/><category term="debian"/></entry><entry><title>Moving blog from self hosting to Github Pages</title><link href="https://copyninja.in/blog/move-back-to-github.html" rel="alternate"/><published>2025-11-16T10:32:00+05:30</published><updated>2025-11-16T10:32:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2025-11-16:/blog/move-back-to-github.html</id><summary type="html">&lt;p class="first last"&gt;Moving the blog to Github pages&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I haven't been blogging as much as I used to. For a while, I've been hosting my
blog on a single-core DigitalOcean droplet, which cost me around $7 per month.
It also hosted my mail server. Most of the time, the droplet was idle, and I
wasn't actively using my personal email much. Since it was self-hosted, I didn't
have confidence that it would always be up, so I relied on Gmail as my personal
email for everything—from banking to social media.&lt;/p&gt;
&lt;p&gt;Now, I feel this cost is just a waste of money, even though it's not huge. So, I
decided to move my blog back to GitHub Pages, now published using GitHub
Workflows. I've stopped my mail server for the time being, and it won't be
reachable for a while. For any personal queries or comments, please reach me on
my &lt;a class="reference external" href="http://scr.im/vasudev"&gt;Personal Gmail&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm not sure how active I'll be with blogging again, but I'll try my best to
return to my old habit of writing at least a post every week or two. Not because
people will read it, but because it gives me the option to explore new things,
experiment, and take notes along the way.&lt;/p&gt;
</content><category term="misc"/><category term="github"/><category term="pages"/><category term="self-hosting"/></entry><entry><title>Signing the systemd-boot on Upgrade Using Dpkg Triggers</title><link href="https://copyninja.in/blog/sign_systemd_boot_trigger.html" rel="alternate"/><published>2024-09-29T13:08:00+05:30</published><updated>2024-09-29T13:08:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2024-09-29:/blog/sign_systemd_boot_trigger.html</id><summary type="html">&lt;p class="first last"&gt;This post discusses signing the systemd-boot EFI binary on upgrade using
the dpkg trigger mechanism.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my previous post on &lt;a class="reference external" href="https://copyninja.in/blog/enable_secureboot_ukify.html"&gt;enabling SecureBoot&lt;/a&gt;, I mentioned that one
pending improvement was signing the &lt;em&gt;systemd-boot&lt;/em&gt; EFI binary with my keys on
every upgrade. In this post, we'll explore the implementation of this process using
dpkg triggers.&lt;/p&gt;
&lt;p&gt;For an excellent introduction to dpkg triggers, refer to this &lt;a class="reference external" href="https://web.archive.org/web/20111022012105/http://www.seanius.net/blog/2009/09/dpkg-triggers-howto/"&gt;archived blog post&lt;/a&gt;.
The source code mentioned in that post can be downloaded from &lt;a class="reference external" href="https://alioth-archive.debian.org/git/users/seanius/dpkg-triggers-example.git.tar.xz"&gt;alioth archive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From &lt;em&gt;/usr/share/doc/dpkg/spec/triggers.txt&lt;/em&gt;, triggers are described as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;em&gt;A dpkg trigger is a facility that allows events caused by one package
but of interest to another package to be recorded and aggregated, and
processed later by the interested package. This feature simplifies
various registration and system-update tasks and reduces duplication
of processing.&lt;/em&gt;&lt;/blockquote&gt;
&lt;p&gt;To implement this, we create a custom package with a single script that signs the
&lt;em&gt;systemd-boot&lt;/em&gt; EFI binary using our key. The script is as simple as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Signing the new systemd-bootx64.efi&amp;quot;&lt;/span&gt;
sbsign&lt;span class="w"&gt; &lt;/span&gt;--key&lt;span class="w"&gt; &lt;/span&gt;/etc/secureboot/db.key&lt;span class="w"&gt; &lt;/span&gt;--cert&lt;span class="w"&gt; &lt;/span&gt;/etc/secureboot/db.crt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;/usr/lib/systemd/boot/efi/systemd-bootx64.efi

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Invoking bootctl install to copy stuff&amp;quot;&lt;/span&gt;
bootctl&lt;span class="w"&gt; &lt;/span&gt;install
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Invoking &lt;em&gt;bootctl install&lt;/em&gt; is optional if we have enabled
&lt;em&gt;systemd-boot-update.service&lt;/em&gt;, which will update the signed bootloader on the next
boot.&lt;/p&gt;
&lt;p&gt;We need to have a &lt;em&gt;triggers&lt;/em&gt; file under the &lt;em&gt;debian/&lt;/em&gt; folder of the package, which
declares its interest in modifications to the path
&lt;em&gt;/usr/lib/systemd/boot/efi/systemd-bootx64.efi&lt;/em&gt;. The trigger file looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# trigger 1 interest on systemd-bootx64.efi
interest-noawait /usr/lib/systemd/boot/efi/systemd-bootx64.efi
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can read about various directives and their meanings that can be used in
the &lt;em&gt;triggers&lt;/em&gt; file in the &lt;em&gt;deb-triggers&lt;/em&gt; man page.&lt;/p&gt;
&lt;p&gt;Once we build and install the package, this request is added to
&lt;em&gt;/var/lib/dpkg/triggers/File&lt;/em&gt;. See the screenshot below after installation of
our package:&lt;/p&gt;
&lt;img alt="installed trigger" class="align-center" src="https://copyninja.in/images/trigger_install.png" /&gt;
&lt;p&gt;To test the functionality, I performed a re-installation of the &lt;em&gt;systemd-boot-efi&lt;/em&gt;
package, which provides the EFI binary for &lt;em&gt;systemd-boot&lt;/em&gt;, using the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--reinstall&lt;span class="w"&gt; &lt;/span&gt;systemd-boot-efi
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;During installation, you can see the debug message being printed in the screenshot below:&lt;/p&gt;
&lt;img alt="systemd-boot-signer triggered" class="align-center" src="https://copyninja.in/images/systemd_boot_sign_triggered.png" /&gt;
&lt;p&gt;To test the &lt;em&gt;systemd-boot-update.service&lt;/em&gt;, I commented out the &lt;em&gt;bootctl install&lt;/em&gt; line
from the above script, performed a reinstallation, and restarted the
&lt;em&gt;systemd-boot-update.service&lt;/em&gt;. Checking the log, I saw the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Sep 29 13:42:51 chamunda systemd[1]: Stopping systemd-boot-update.service - Automatic Boot Loader Update...
Sep 29 13:42:51 chamunda systemd[1]: Starting systemd-boot-update.service - Automatic Boot Loader Update...
Sep 29 13:42:51 chamunda bootctl[1801516]: Skipping &amp;quot;/efi/EFI/systemd/systemd-bootx64.efi&amp;quot;, same boot loader version in place already.
Sep 29 13:42:51 chamunda bootctl[1801516]: Skipping &amp;quot;/efi/EFI/BOOT/BOOTX64.EFI&amp;quot;, same boot loader version in place already.
Sep 29 13:42:51 chamunda bootctl[1801516]: Skipping &amp;quot;/efi/EFI/BOOT/BOOTX64.EFI&amp;quot;, same boot loader version in place already.
Sep 29 13:42:51 chamunda systemd[1]: Finished systemd-boot-update.service - Automatic Boot Loader Update.
Sep 29 13:43:37 chamunda systemd[1]: systemd-boot-update.service: Deactivated successfully.
Sep 29 13:43:37 chamunda systemd[1]: Stopped systemd-boot-update.service - Automatic Boot Loader Update.
Sep 29 13:43:37 chamunda systemd[1]: Stopping systemd-boot-update.service - Automatic Boot Loader Update...
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Indeed, the service attempted to copy the bootloader but did not do so because
there was no actual update to the binary; it was just a reinstallation trigger.&lt;/p&gt;
&lt;p&gt;The complete code for this package can be found &lt;a class="reference external" href="https://github.com/copyninja/systemd-boot-signer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With this post the entire series on using  UKI to Secureboot with Debian comes
to an end. Happy hacking!.&lt;/p&gt;
</content><category term="devops"/><category term="systemd"/><category term="dpkg"/><category term="triggers"/><category term="uefi"/><category term="debian"/></entry><entry><title>Disabling Lockdown Mode with Secure Boot on Distro Kernel</title><link href="https://copyninja.in/blog/disable_lockdown_on_distro_kernel.html" rel="alternate"/><published>2024-09-26T22:13:00+05:30</published><updated>2024-09-26T22:13:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2024-09-26:/blog/disable_lockdown_on_distro_kernel.html</id><summary type="html">&lt;p class="first last"&gt;This post discusses a method to disable kernel lockdown mode on a
distribution kernel when Secure Boot is enabled.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my &lt;a class="reference external" href="https://copyninja.in/blog/enable_secureboot_ukify.html"&gt;previous post&lt;/a&gt;,
I mentioned that Lockdown mode is activated when Secure Boot is enabled. One way
to override this was to use a self-compiled upstream kernel. However, sometimes
we might want to use the distribution kernel itself. This post explains how to
disable lockdown mode while keeping Secure Boot enabled with a distribution
kernel.&lt;/p&gt;
&lt;div class="section" id="understanding-secure-boot-detection"&gt;
&lt;h2&gt;Understanding Secure Boot Detection&lt;/h2&gt;
&lt;p&gt;To begin, we need to understand how the kernel detects if Secure Boot is
enabled. This is done by the &lt;em&gt;efi_get_secureboot&lt;/em&gt; function, as shown in the
image below:&lt;/p&gt;
&lt;img alt="Secure Boot status check" class="align-center" src="https://copyninja.in/images/secureboot_code.png" /&gt;
&lt;/div&gt;
&lt;div class="section" id="disabling-kernel-lockdown"&gt;
&lt;h2&gt;Disabling Kernel Lockdown&lt;/h2&gt;
&lt;p&gt;The kernel code uses the value of MokSBStateRT to identify the Secure Boot state,
assuming that Secure Boot can only be enabled via shim. This assumption holds true
when using the Microsoft certificate for signature validation (as Microsoft currently
only signs shim). However, if we're using our own keys, we don't need shim and can
sign the bootloader ourselves. In this case, the Secure Boot state of the system
doesn't need to be tied to the MokSBStateRT variable.&lt;/p&gt;
&lt;p&gt;To disable kernel lockdown, we need to set the UEFI runtime variable
&lt;em&gt;MokSBStateRT&lt;/em&gt;. This essentially tricks the kernel into thinking Secure Boot is
disabled when it's actually enabled. This is achieved using a UEFI
&lt;em&gt;initializing&lt;/em&gt; driver.&lt;/p&gt;
&lt;p&gt;The code for this was written by an anonymous colleague who also assisted me
with various configuration guidance for setting up UKI and Secure Boot on my
system. The code is available &lt;a class="reference external" href="https://codeberg.org/scarletstorm/lockdown-disable/src/branch/main"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;Detailed instructions for compiling and deploying the code are provided in the
repository, so I won't repeat them here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="results"&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;I've tested this method with the default distribution kernel on my Debian
unstable system, and it successfully disables lockdown while maintaining Secure
Boot integrity. See the screenshot below for confirmation:&lt;/p&gt;
&lt;img alt="Distribution kernel lockdown disabled" class="align-center" src="https://copyninja.in/images/distro_kernel_lockdown.png" /&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="debian"/><category term="systemd"/><category term="secureboot"/><category term="lockdown"/></entry><entry><title>Note to Self: Enabling Secure Boot with UKI on Debian</title><link href="https://copyninja.in/blog/enable_secureboot_ukify.html" rel="alternate"/><published>2024-09-24T11:30:00+05:30</published><updated>2024-09-24T11:30:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2024-09-24:/blog/enable_secureboot_ukify.html</id><summary type="html">&lt;p class="first last"&gt;This post explains how to enable self-signed Secure Boot with Unified
Kernel Image (UKI) on Debian.&lt;/p&gt;
</summary><content type="html">&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;&lt;em&gt;This post is a continuation of my previous article on enabling the Unified
Kernel Image (UKI) on Debian.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://copyninja.in/blog/enable_ukify_debian.html"&gt;Enabling Unified Kernel Image on Debian&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this guide, we'll implement Secure Boot by taking full control of the device,
removing preinstalled keys, and installing our own. For a comprehensive overview
of the benefits and process, refer to this excellent post from &lt;a class="reference external" href="https://www.rodsbooks.com/efi-bootloaders/controlling-sb.html"&gt;rodsbooks&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="key-components"&gt;
&lt;h2&gt;Key Components&lt;/h2&gt;
&lt;p&gt;To implement Secure Boot, we need three essential keys:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Platform Key (PK): The top-level key in Secure Boot, typically provided by
the motherboard manufacturer. We'll replace the vendor-supplied PK with our
own for complete control.&lt;/li&gt;
&lt;li&gt;Key Exchange Key (KEK): Used to sign updates for the Signatures Database and
Forbidden Signatures Database.&lt;/li&gt;
&lt;li&gt;Database Key (DB): Used to sign or verify binaries (bootloaders, boot
managers, shells, drivers, etc.).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There's also a Forbidden Signature Key (dbx), which is the opposite of the DB
key. We won't be generating this key in this guide.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="preparing-for-key-enrollment"&gt;
&lt;h2&gt;Preparing for Key Enrollment&lt;/h2&gt;
&lt;p&gt;Before enrolling our keys, we need to put the device in &lt;em&gt;Secure Boot Setup
Mode&lt;/em&gt;. Verify the status using the &lt;tt class="docutils literal"&gt;bootctl status&lt;/tt&gt; command. You should see
output similar to the following image:&lt;/p&gt;
&lt;img alt="UEFI Setup mode" class="align-center" src="https://copyninja.in/images/uefi_setupmode.png" /&gt;
&lt;/div&gt;
&lt;div class="section" id="generating-keys"&gt;
&lt;h2&gt;Generating Keys&lt;/h2&gt;
&lt;p&gt;Follow &lt;a class="reference external" href="https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#Creating_keys"&gt;these instructions from the Arch Wiki&lt;/a&gt;
to generate the keys manually. You'll need the &lt;tt class="docutils literal"&gt;efitools&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;openssl&lt;/tt&gt;
packages. I recommend using &lt;tt class="docutils literal"&gt;rsa:2048&lt;/tt&gt; as the key size for better
compatibility with older firmware.&lt;/p&gt;
&lt;p&gt;After generating the keys, copy all &lt;tt class="docutils literal"&gt;.auth&lt;/tt&gt; files to the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/efi/loader/keys/&amp;lt;hostname&amp;gt;/&lt;/span&gt;&lt;/tt&gt; folder. For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;❯&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;/efi/loader/keys/chamunda
db.auth&lt;span class="w"&gt;  &lt;/span&gt;KEK.auth&lt;span class="w"&gt;  &lt;/span&gt;PK.auth
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="signing-the-bootloader"&gt;
&lt;h2&gt;Signing the Bootloader&lt;/h2&gt;
&lt;p&gt;Sign the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-boot&lt;/span&gt;&lt;/tt&gt; bootloader with your new keys:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sbsign&lt;span class="w"&gt; &lt;/span&gt;--key&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;path-to&lt;span class="w"&gt; &lt;/span&gt;db.key&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--cert&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;path-to&lt;span class="w"&gt; &lt;/span&gt;db.crt&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;/usr/lib/systemd/boot/efi/systemd-bootx64.efi
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Install the signed bootloader using &lt;tt class="docutils literal"&gt;bootctl install&lt;/tt&gt;. The output should
resemble this:&lt;/p&gt;
&lt;img alt="bootctl install" class="align-center" src="https://copyninja.in/images/bootctl_install.png" /&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;&lt;em&gt;If you encounter warnings about mount options, update your fstab with the
`umask=0077` option for the EFI partition.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Verify the signature using &lt;tt class="docutils literal"&gt;sbsign &lt;span class="pre"&gt;--verify&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;img alt="sbsign verify" class="align-center" src="https://copyninja.in/images/sbsign_verify_systemdboot.png" /&gt;
&lt;/div&gt;
&lt;div class="section" id="configuring-uki-for-secure-boot"&gt;
&lt;h2&gt;Configuring UKI for Secure Boot&lt;/h2&gt;
&lt;p&gt;Update the &lt;tt class="docutils literal"&gt;/etc/kernel/uki.conf&lt;/tt&gt; file with your key paths:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;SecureBootPrivateKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/path/to/db.key&lt;/span&gt;
&lt;span class="na"&gt;SecureBootCertificate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/path/to/db.crt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="signing-the-uki-image"&gt;
&lt;h2&gt;Signing the UKI Image&lt;/h2&gt;
&lt;p&gt;On Debian, use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;dpkg-reconfigure&lt;/span&gt;&lt;/tt&gt; to sign the UKI image for each kernel:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;linux-image-&lt;span class="k"&gt;$(&lt;/span&gt;uname&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Repeat for other kernel versions if necessary&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You should see output similar to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;linux-image-&lt;span class="k"&gt;$(&lt;/span&gt;uname&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="k"&gt;)&lt;/span&gt;
/etc/kernel/postinst.d/dracut:
dracut:&lt;span class="w"&gt; &lt;/span&gt;Generating&lt;span class="w"&gt; &lt;/span&gt;/boot/initrd.img-6.10.9-amd64
Updating&lt;span class="w"&gt; &lt;/span&gt;kernel&lt;span class="w"&gt; &lt;/span&gt;version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.10.9-amd64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemd-boot...
Signing&lt;span class="w"&gt; &lt;/span&gt;unsigned&lt;span class="w"&gt; &lt;/span&gt;original&lt;span class="w"&gt; &lt;/span&gt;image
Using&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;file:&lt;span class="w"&gt; &lt;/span&gt;/etc/kernel/uki.conf
+&lt;span class="w"&gt; &lt;/span&gt;sbverify&lt;span class="w"&gt; &lt;/span&gt;--list&lt;span class="w"&gt; &lt;/span&gt;/boot/vmlinuz-6.10.9-amd64
+&lt;span class="w"&gt; &lt;/span&gt;sbsign&lt;span class="w"&gt; &lt;/span&gt;--key&lt;span class="w"&gt; &lt;/span&gt;/home/vasudeva.sk/Documents/personal/secureboot/db.key&lt;span class="w"&gt; &lt;/span&gt;--cert&lt;span class="w"&gt; &lt;/span&gt;/home/vasudeva.sk/Documents/personal/secureboot/db.crt&lt;span class="w"&gt; &lt;/span&gt;/tmp/ukicc7vcxhy&lt;span class="w"&gt; &lt;/span&gt;--output&lt;span class="w"&gt; &lt;/span&gt;/tmp/kernel-install.staging.QLeGLn/uki.efi
Wrote&lt;span class="w"&gt; &lt;/span&gt;signed&lt;span class="w"&gt; &lt;/span&gt;/tmp/kernel-install.staging.QLeGLn/uki.efi
/etc/kernel/postinst.d/zz-systemd-boot:
Installing&lt;span class="w"&gt; &lt;/span&gt;kernel&lt;span class="w"&gt; &lt;/span&gt;version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.10.9-amd64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemd-boot...
Signing&lt;span class="w"&gt; &lt;/span&gt;unsigned&lt;span class="w"&gt; &lt;/span&gt;original&lt;span class="w"&gt; &lt;/span&gt;image
Using&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;file:&lt;span class="w"&gt; &lt;/span&gt;/etc/kernel/uki.conf
+&lt;span class="w"&gt; &lt;/span&gt;sbverify&lt;span class="w"&gt; &lt;/span&gt;--list&lt;span class="w"&gt; &lt;/span&gt;/boot/vmlinuz-6.10.9-amd64
+&lt;span class="w"&gt; &lt;/span&gt;sbsign&lt;span class="w"&gt; &lt;/span&gt;--key&lt;span class="w"&gt; &lt;/span&gt;/home/vasudeva.sk/Documents/personal/secureboot/db.key&lt;span class="w"&gt; &lt;/span&gt;--cert&lt;span class="w"&gt; &lt;/span&gt;/home/vasudeva.sk/Documents/personal/secureboot/db.crt&lt;span class="w"&gt; &lt;/span&gt;/tmp/ukit7r1hzep&lt;span class="w"&gt; &lt;/span&gt;--output&lt;span class="w"&gt; &lt;/span&gt;/tmp/kernel-install.staging.dWVt5s/uki.efi
Wrote&lt;span class="w"&gt; &lt;/span&gt;signed&lt;span class="w"&gt; &lt;/span&gt;/tmp/kernel-install.staging.dWVt5s/uki.efi
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="enrolling-keys-in-firmware"&gt;
&lt;h2&gt;Enrolling Keys in Firmware&lt;/h2&gt;
&lt;p&gt;Use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-boot&lt;/span&gt;&lt;/tt&gt; to enroll your keys:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;reboot&lt;span class="w"&gt; &lt;/span&gt;--boot-loader-menu&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Select the enroll option with your hostname in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-boot&lt;/span&gt;&lt;/tt&gt; menu.&lt;/p&gt;
&lt;p&gt;After key enrollment, the system will reboot into the newly signed kernel.
Verify with &lt;tt class="docutils literal"&gt;bootctl&lt;/tt&gt;:&lt;/p&gt;
&lt;img alt="uefi enabled" class="align-center" src="https://copyninja.in/images/bootctl_uefi_enabled.png" /&gt;
&lt;/div&gt;
&lt;div class="section" id="dealing-with-lockdown-mode"&gt;
&lt;h2&gt;Dealing with Lockdown Mode&lt;/h2&gt;
&lt;p&gt;Secure Boot enables lockdown mode on distro-shipped kernels, which restricts
certain features like kprobes/BPF and DKMS drivers. To avoid this, consider
compiling the upstream kernel directly, which doesn't enable lockdown mode by
default.&lt;/p&gt;
&lt;p&gt;As Linus Torvalds has stated, &amp;quot;there is no reason to tie Secure Boot to lockdown
LSM.&amp;quot; You can read more about &lt;a class="reference external" href="https://www.phoronix.com/news/UEFI-Kernel-Lockdown-Concerns"&gt;Torvalds' opinion on UEFI tied with lockdown&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="next-steps"&gt;
&lt;h2&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;One thing that remains is automating the signing of systemd-boot on upgrade,
which is currently a manual process. I'm exploring dpkg triggers for achieving
this, and if I succeed, I will write a new post with details.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="acknowledgments"&gt;
&lt;h2&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;Special thanks to my anonymous colleague who provided invaluable assistance
throughout this process.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="debian"/><category term="secureboot"/><category term="systemd"/><category term="uki"/></entry><entry><title>Note to Self: Enabling Unified Kernel Image on Debian</title><link href="https://copyninja.in/blog/enable_ukify_debian.html" rel="alternate"/><published>2024-09-19T11:40:00+05:30</published><updated>2024-09-19T11:40:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2024-09-19:/blog/enable_ukify_debian.html</id><summary type="html">&lt;p class="first last"&gt;Enabling systemd-ukify based booting on Debian&lt;/p&gt;
</summary><content type="html">&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;&lt;em&gt;These steps may not work on your system if you are using the default Debian
installation. This guide assumes that your system is using systemd-boot as the
bootloader, which is explained in the post linked below.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://copyninja.in/blog/live_install_debian.html"&gt;Install Debian from grml-liveboot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A unified kernel image (UKI) is a single executable that can be booted directly
from UEFI firmware or automatically sourced by bootloaders with little or no
configuration. It combines a UEFI boot stub program like
systemd-stub(7), a Linux kernel image, an initrd, and additional resources into
a single UEFI PE file.&lt;/p&gt;
&lt;p&gt;systemd-boot already provides a hook for kernel installation via
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/kernel/postinst.d/zz-systemd-boot&lt;/span&gt;&lt;/tt&gt;. We just need a couple of additional
configurations to generate the UKI image.&lt;/p&gt;
&lt;div class="section" id="installation-and-configuration"&gt;
&lt;h2&gt;Installation and Configuration&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Install the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-ukify&lt;/span&gt;&lt;/tt&gt; package:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;systemd-ukify
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Create the following configuration in &lt;tt class="docutils literal"&gt;/etc/kernel/install.conf&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;uki&lt;/span&gt;
&lt;span class="na"&gt;initrd_generator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dracut&lt;/span&gt;
&lt;span class="na"&gt;uki_generator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ukify&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This configuration specifies how to generate the UKI image for the installed
kernel and which generator to use.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Define the kernel command line for the UKI image. Create &lt;tt class="docutils literal"&gt;/etc/kernel/uki.conf&lt;/tt&gt; with the following content:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[UKI]&lt;/span&gt;
&lt;span class="na"&gt;Cmdline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;@/etc/kernel/cmdline&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="generating-the-uki-image"&gt;
&lt;h2&gt;Generating the UKI Image&lt;/h2&gt;
&lt;p&gt;To apply these changes, regenerate the UKI image for the currently running kernel:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;linux-image-&lt;span class="k"&gt;$(&lt;/span&gt;uname&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="verification"&gt;
&lt;h2&gt;Verification&lt;/h2&gt;
&lt;p&gt;Use the &lt;tt class="docutils literal"&gt;bootctl list&lt;/tt&gt; command to verify the presence of a &amp;quot;Type #2&amp;quot; entry for the current kernel. The output should look similar to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;bootctl list
      type: Boot Loader Specification Type #2 (.efi)
     title: Debian GNU/Linux trixie/sid (2d0080583f1a4127ac0b073b1a9d3e61-6.10.9-amd64.efi) (default) (selected)
        id: 2d0080583f1a4127ac0b073b1a9d3e61-6.10.9-amd64.efi
    source: /boot/efi/EFI/Linux/2d0080583f1a4127ac0b073b1a9d3e61-6.10.9-amd64.efi
  sort-key: debian
     linux: /boot/efi/EFI/Linux/2d0080583f1a4127ac0b073b1a9d3e61-6.10.9-amd64.efi
   options: systemd.gpt_auto=no quiet root=LABEL=root_disk ro systemd.machine_id=2d0080583f1a4127ac0b073b1a9d3e61

      type: Boot Loader Specification Type #2 (.efi)
     title: Debian GNU/Linux trixie/sid (2d0080583f1a4127ac0b073b1a9d3e61-6.10.7-amd64.efi)
        id: 2d0080583f1a4127ac0b073b1a9d3e61-6.10.7-amd64.efi
    source: /boot/efi/EFI/Linux/2d0080583f1a4127ac0b073b1a9d3e61-6.10.7-amd64.efi
  sort-key: debian
     linux: /boot/efi/EFI/Linux/2d0080583f1a4127ac0b073b1a9d3e61-6.10.7-amd64.efi
   options: systemd.gpt_auto=no quiet root=LABEL=root_disk ro systemd.machine_id=2d0080583f1a4127ac0b073b1a9d3e61

      type: Automatic
     title: Reboot Into Firmware Interface
        id: auto-reboot-to-firmware-setup
    source: /sys/firmware/efi/efivars/LoaderEntries-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="cleanup-and-reboot"&gt;
&lt;h2&gt;Cleanup and Reboot&lt;/h2&gt;
&lt;p&gt;Once the &amp;quot;Type #2&amp;quot; entries are generated, remove any &amp;quot;Type #1&amp;quot; entries using the &lt;tt class="docutils literal"&gt;bootctl unlink&lt;/tt&gt; command. After this, reboot your system to boot from the UKI-based image.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="future-considerations"&gt;
&lt;h2&gt;Future Considerations&lt;/h2&gt;
&lt;p&gt;The primary use case for a UKI image is secure boot. Signing the UKI image can also be configured in the settings above, but this guide does not cover that process as it requires setting up secure boot on your system.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="debian"/><category term="systemd"/><category term="ukify"/></entry><entry><title>Cloning a laptop over NVME TCP</title><link href="https://copyninja.in/blog/clone_laptop_nvmet.html" rel="alternate"/><published>2024-03-10T17:15:00+05:30</published><updated>2024-03-10T17:15:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2024-03-10:/blog/clone_laptop_nvmet.html</id><summary type="html">&lt;p class="first last"&gt;Cloning old laptop over NVME TCP&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Recently, I got a new laptop and had to set it up so I could start using it. But
I wasn't really in the mood to go through the same old steps which I had
explained in this &lt;a class="reference external" href="https://copyninja.in/blog/live_install_debian.html"&gt;post earlier&lt;/a&gt;. I was complaining about
this to my colleague, and there came the suggestion of why not copy the entire
disk to the new laptop. Though it sounded like an interesting idea to me, I had
my doubts, so here is what I told him in return.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;I don't have the tools to open my old laptop and connect the new disk over
USB to my new laptop.&lt;/li&gt;
&lt;li&gt;I use full disk encryption, and my old laptop has a 512GB disk, whereas the
new laptop has a 1TB NVME, and I'm not so familiar with resizing LUKS.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;He promptly suggested both could be done. For step 1, just expose the disk using
NVME over TCP and connect it over the network and do a full disk copy, and the
rest is pretty simple to achieve. In short, he suggested the following:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Export the disk using nvmet-tcp from the old laptop.&lt;/li&gt;
&lt;li&gt;Do a disk copy to the new laptop.&lt;/li&gt;
&lt;li&gt;Resize the partition to use the full 1TB.&lt;/li&gt;
&lt;li&gt;Resize LUKS.&lt;/li&gt;
&lt;li&gt;Finally, resize the BTRFS root disk.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="exporting-disk-over-nvme-tcp"&gt;
&lt;h2&gt;Exporting Disk over NVME TCP&lt;/h2&gt;
&lt;p&gt;The easiest way suggested by my colleague to do this is using
&lt;a class="reference external" href="https://www.freedesktop.org/software/systemd/man/latest/systemd-storagetm.service.html"&gt;systemd-storagetm.service&lt;/a&gt;.
This service can be invoked by simply booting into &lt;em&gt;storage-target-mode.target&lt;/em&gt;
by specifying &lt;em&gt;rd.systemd.unit=storage-target-mode.target&lt;/em&gt;. But he suggested not
to use this as I need to tweak the dracut initrd image to involve network
services as well as configuring WiFi from this mode is a painful thing to do.&lt;/p&gt;
&lt;p&gt;So alternatively, I simply booted both my laptops with GRML rescue CD. And the
following step was done to export the NVME disk on my current laptop using the
nvmet-tcp module of Linux:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;modprobe&lt;span class="w"&gt; &lt;/span&gt;nvmet-tcp
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/config/nvmet
mkdir&lt;span class="w"&gt; &lt;/span&gt;ports/0
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ports/0
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ipv4&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;addr_adrfam
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.0.0.0&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;addr_traaddr
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4420&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;addr_trsvcid
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tcp&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;addr_trtype

&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/config/nvmet/subsystems
mkdir&lt;span class="w"&gt; &lt;/span&gt;testnqn
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;testnqn/allow_any_host
mkdir&lt;span class="w"&gt; &lt;/span&gt;testnqn/namespaces/1

&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;testnqn
&lt;span class="c1"&gt;# replace the device name with the disk you want to export&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/dev/nvme0n1&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;namespaces/1/device_path
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;namespaces/1/enable

ln&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;../../subsystems/testnqn&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/config/nvmet/ports/0/subsystems/testnqn
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These steps ensure that the device is now exported using NVME over TCP. The next
step is to detect this on the new laptop and connect the device:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;nvme&lt;span class="w"&gt; &lt;/span&gt;discover&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;tcp&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;ip&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4420&lt;/span&gt;
nvme&lt;span class="w"&gt; &lt;/span&gt;connectl-all&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;tcp&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4420&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, &lt;tt class="docutils literal"&gt;nvme list&lt;/tt&gt; shows the device which is connected to the new laptop,
and we can proceed with the next step, which is to do the disk copy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="copying-the-disk"&gt;
&lt;h2&gt;Copying the Disk&lt;/h2&gt;
&lt;p&gt;I simply used the &lt;tt class="docutils literal"&gt;dd&lt;/tt&gt; command to copy the root disk to my new laptop. Since
the new laptop didn't have an Ethernet port, I had to rely only on WiFi, and it
took about 7 and a half hours to copy the entire 512GB to the new laptop. The
speed at which I was copying was about 18-20MB/s. The other option would have
been to create an initial partition and file system and do an rsync of the root
disk or use BTRFS itself for file system transfer.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/nvme2n1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/nvme0n1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;40M
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="resizing-partition-and-luks-container"&gt;
&lt;h2&gt;Resizing Partition and LUKS Container&lt;/h2&gt;
&lt;p&gt;The final part was very easy. When I launched &lt;tt class="docutils literal"&gt;parted&lt;/tt&gt;, it detected that the
partition table does not match the disk size and asked if it can fix it, and I
said yes. Next, I had to install &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;cloud-guest-utils&lt;/span&gt;&lt;/tt&gt; to get &lt;tt class="docutils literal"&gt;growpart&lt;/tt&gt; to
fix the second partition, and the following command extended the partition to
the full 1TB:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;growpart&lt;span class="w"&gt; &lt;/span&gt;/dev/nvem0n1&lt;span class="w"&gt; &lt;/span&gt;p2
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, I used &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;cryptsetup-resize&lt;/span&gt;&lt;/tt&gt; to increase the LUKS container size.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cryptsetup&lt;span class="w"&gt; &lt;/span&gt;luksOpen&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0n1p2&lt;span class="w"&gt; &lt;/span&gt;ENC
cryptsetup&lt;span class="w"&gt; &lt;/span&gt;resize&lt;span class="w"&gt; &lt;/span&gt;ENC
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, I rebooted into the disk, and everything worked fine. After logging
into the system, I resized the BTRFS file system. BTRFS requires the system to
be mounted for resize, so I could not attempt it in live boot.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;btfs&lt;span class="w"&gt; &lt;/span&gt;fielsystem&lt;span class="w"&gt; &lt;/span&gt;resize&lt;span class="w"&gt; &lt;/span&gt;max&lt;span class="w"&gt; &lt;/span&gt;/
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The only benefit of this entire process is that I have a new laptop, but I still
feel like I'm using my existing laptop. Typically, setting up a new laptop takes
about a week or two to completely get adjusted, but in this case, that entire
time is saved.&lt;/p&gt;
&lt;p&gt;An added benefit is that I learned how to export disks using NVME over TCP,
thanks to my colleague. This new knowledge adds to the value of the experience.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="debian"/><category term="nvmet"/><category term="clone"/></entry><entry><title>Using LUKS-Encrypted USB Stick with TPM2 Integration</title><link href="https://copyninja.in/blog/luks2_tpm_mount.html" rel="alternate"/><published>2023-07-09T13:17:00+05:30</published><updated>2023-07-09T13:17:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2023-07-09:/blog/luks2_tpm_mount.html</id><summary type="html">&lt;p class="first last"&gt;Experimenting with systemd-cryptenroll to mount luks2 encrypted usb
device&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I use a LUKS-encrypted USB stick to store my GPG and SSH keys, which acts as a
backup and portable key setup when working on different laptops. One
inconvenience with LUKS-encrypted USB sticks is that you need to enter the
password every time you want to mount the device, either through a Window
Manager like KDE or using the &lt;cite&gt;cryptsetup luksOpen&lt;/cite&gt; command. Fortunately, many
laptops nowadays come equipped with TPM2 modules, which can be utilized to
automatically decrypt the device and subsequently mount it. In this post, we'll
explore the usage of &lt;em&gt;systemd-cryptenroll&lt;/em&gt; for this purpose, along with udev
rules and a set of scripts to automate the mounting of the encrypted USB.&lt;/p&gt;
&lt;p&gt;First, ensure that your device has a TPM2 module. You can run the following
command to check:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;journalctl&lt;span class="w"&gt; &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;--grep&lt;span class="o"&gt;=&lt;/span&gt;tpm2
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The output should resemble the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Jul&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;:57:32&lt;span class="w"&gt; &lt;/span&gt;bhairava&lt;span class="w"&gt; &lt;/span&gt;kernel:&lt;span class="w"&gt; &lt;/span&gt;ACPI:&lt;span class="w"&gt; &lt;/span&gt;SSDT&lt;span class="w"&gt; &lt;/span&gt;0x00000000BBEFC000&lt;span class="w"&gt; &lt;/span&gt;0003C6&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;v02
LENOVO&lt;span class="w"&gt; &lt;/span&gt;Tpm2Tabl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;00001000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;INTL&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20160422&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jul&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;:57:32&lt;span class="w"&gt; &lt;/span&gt;bhairava&lt;span class="w"&gt; &lt;/span&gt;kernel:
ACPI:&lt;span class="w"&gt; &lt;/span&gt;TPM2&lt;span class="w"&gt; &lt;/span&gt;0x00000000BBEFB000&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;000034&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;v03&lt;span class="w"&gt; &lt;/span&gt;LENOVO&lt;span class="w"&gt; &lt;/span&gt;TP-R0D&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;00000830&lt;/span&gt;
PTEC&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;00000002&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jul&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;:57:32&lt;span class="w"&gt; &lt;/span&gt;bhairava&lt;span class="w"&gt; &lt;/span&gt;kernel:&lt;span class="w"&gt; &lt;/span&gt;ACPI:&lt;span class="w"&gt; &lt;/span&gt;Reserving&lt;span class="w"&gt; &lt;/span&gt;TPM2&lt;span class="w"&gt; &lt;/span&gt;table
memory&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;mem&lt;span class="w"&gt; &lt;/span&gt;0xbbefb000-0xbbefb033&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also use the &lt;cite&gt;systemd-cryptenroll&lt;/cite&gt; command to check for the availability
of a TPM2 device on your laptop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemd-cryptenroll&lt;span class="w"&gt; &lt;/span&gt;--tpm2-device&lt;span class="o"&gt;=&lt;/span&gt;list
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The output will be something like following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;blog&lt;span class="w"&gt; &lt;/span&gt;git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemd-cryptenroll&lt;span class="w"&gt; &lt;/span&gt;--tpm2-device&lt;span class="o"&gt;=&lt;/span&gt;list
PATH&lt;span class="w"&gt;        &lt;/span&gt;DEVICE&lt;span class="w"&gt;      &lt;/span&gt;DRIVER
/dev/tpmrm0&lt;span class="w"&gt; &lt;/span&gt;MSFT0101:00&lt;span class="w"&gt; &lt;/span&gt;tpm_tis
➜&lt;span class="w"&gt;  &lt;/span&gt;blog&lt;span class="w"&gt; &lt;/span&gt;git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, ensure that you have connected your encrypted USB device. Note that
&lt;cite&gt;systemd-cryptenroll&lt;/cite&gt; only works with LUKS2 and not LUKS1. If your device is
LUKS1-encrypted, you may encounter an error while enrolling the device,
complaining about the LUKS2 superblock not found.&lt;/p&gt;
&lt;p&gt;To determine if your device uses a LUKS1 header or LUKS2, use the &lt;cite&gt;cryptsetup
luksDump &amp;lt;device&amp;gt;&lt;/cite&gt; command. If it is LUKS1, the header will begin with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;LUKS&lt;span class="w"&gt; &lt;/span&gt;header&lt;span class="w"&gt; &lt;/span&gt;information&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb1

Version:&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
Cipher&lt;span class="w"&gt; &lt;/span&gt;name:&lt;span class="w"&gt;    &lt;/span&gt;aes
Cipher&lt;span class="w"&gt; &lt;/span&gt;mode:&lt;span class="w"&gt;    &lt;/span&gt;xts-plain64
Hash&lt;span class="w"&gt; &lt;/span&gt;spec:&lt;span class="w"&gt;      &lt;/span&gt;sha256
Payload&lt;span class="w"&gt; &lt;/span&gt;offset:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Converting from LUKS1 to LUKS2 is a simple process, but for safety, ensure that
you backup the header using the &lt;cite&gt;cryptsetup luksHeaderBackup&lt;/cite&gt; command. Once
backed up, use the following command to convert the header to LUKS2:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;cryptsetup&lt;span class="w"&gt; &lt;/span&gt;convert&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="w"&gt; &lt;/span&gt;luks2&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After conversion, the header will look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Version:&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
Epoch:&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
Metadata&lt;span class="w"&gt; &lt;/span&gt;area:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;16384&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;bytes&lt;span class="o"&gt;]&lt;/span&gt;
Keyslots&lt;span class="w"&gt; &lt;/span&gt;area:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2064384&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;bytes&lt;span class="o"&gt;]&lt;/span&gt;
UUID:&lt;span class="w"&gt;           &lt;/span&gt;000b2670-be4a-41b4-98eb-9adbd12a7616
Label:&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;label&lt;span class="o"&gt;)&lt;/span&gt;
Subsystem:&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;subsystem&lt;span class="o"&gt;)&lt;/span&gt;
Flags:&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;flags&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The next step is to enroll the new LUKS key for the encrypted device using
&lt;cite&gt;systemd-cryptenroll&lt;/cite&gt;. Run the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemd-cryptenroll&lt;span class="w"&gt; &lt;/span&gt;--tpm2-device&lt;span class="o"&gt;=&lt;/span&gt;/dev/tpmrm0&lt;span class="w"&gt; &lt;/span&gt;--tpm2-pcrs&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0+7&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This command will prompt you to provide the existing key to unseal the device.
It will then add a new random key to the volume, allowing it to be unlocked in
addition to the existing keys. Additionally, it will bind this new key to PCRs 0
and 7, representing the system firmware and Secure Boot state.&lt;/p&gt;
&lt;p&gt;If there is only one TPM device on the system, you can use &lt;cite&gt;--tpm2-device=auto&lt;/cite&gt;
to automatically select the device. To confirm that the new key has been
enrolled, you can dump the LUKS configuration and look for a &lt;cite&gt;systemd-tpm2&lt;/cite&gt;
token entry, as well as an additional entry in the Keyslots section.&lt;/p&gt;
&lt;p&gt;To test the setup, you can use the &lt;cite&gt;/usr/lib/systemd/systemd-cryptsetup&lt;/cite&gt; command. Additionally, you can check if the device is unsealed by using &lt;cite&gt;lsblk&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;/usr/lib/systemd/systemd-cryptsetup&lt;span class="w"&gt; &lt;/span&gt;attach&lt;span class="w"&gt; &lt;/span&gt;GPG_USB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/dev/sdb1&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;tpm2-device&lt;span class="o"&gt;=&lt;/span&gt;auto

lsblk
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;cite&gt;lsblk&lt;/cite&gt; command should display the unsealed and mounted device, like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;NAME&lt;span class="w"&gt;        &lt;/span&gt;MAJ:MIN&lt;span class="w"&gt; &lt;/span&gt;RM&lt;span class="w"&gt;   &lt;/span&gt;SIZE&lt;span class="w"&gt; &lt;/span&gt;RO&lt;span class="w"&gt; &lt;/span&gt;TYPE&lt;span class="w"&gt;  &lt;/span&gt;MOUNTPOINTS
sda&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;:0&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;223&lt;/span&gt;.6G&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;disk
├─sda1&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;:1&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;976M&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;part&lt;span class="w"&gt;  &lt;/span&gt;/boot/efi
└─sda2&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;:2&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;222&lt;/span&gt;.6G&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;part
&lt;span class="w"&gt;  &lt;/span&gt;└─root&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;254&lt;/span&gt;:0&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;222&lt;/span&gt;.6G&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;crypt&lt;span class="w"&gt; &lt;/span&gt;/
sdb&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;:16&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;.5G&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;disk
└─sdb1&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;:17&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;.5G&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;part
&lt;span class="w"&gt;  &lt;/span&gt;└─GPG_USB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;254&lt;/span&gt;:1&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;.5G&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;crypt&lt;span class="w"&gt; &lt;/span&gt;/media/vasudev/GPG_USB
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="auto-mounting-the-device"&gt;
&lt;h2&gt;Auto Mounting the device&lt;/h2&gt;
&lt;p&gt;Now that we have solved the initial problem of unsealing the USB device using
TPM2 instead of manually entering the key, the next step is to automatically
mount the device upon insertion and remove the mapping when the device is
removed. This can be achieved using the following udev rules:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ACTION==&amp;quot;add&amp;quot;, KERNEL==&amp;quot;sd*&amp;quot;, ENV{DEVTYPE}==&amp;quot;partition&amp;quot;, ENV{ID_BUS}==&amp;quot;usb&amp;quot;, ENV{SYSTEMD_WANTS}=&amp;quot;mount-gpg-usb@$env{DEVNAME}.service&amp;quot;
ACTION==&amp;quot;remove&amp;quot;, KERNEL==&amp;quot;sd*&amp;quot;, ENV{DEVTYPE}==&amp;quot;partition&amp;quot;, ENV{ID_BUS}==&amp;quot;usb&amp;quot;, RUN+=&amp;quot;/usr/local/bin/umount_enc_usb.sh &amp;#39;%E{ID_FS_UUID}&amp;#39;&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When a device is added, a systemd service is triggered to mount the device at a
specific location. Initially, I used a script with the &lt;cite&gt;RUN&lt;/cite&gt; directive, but it
resulted in an exit code of &lt;cite&gt;32&lt;/cite&gt;. This might be due to &lt;cite&gt;systemd-cryptsetup&lt;/cite&gt;
taking some time to return, causing udev to time out. To address this, I opted
to use a systemd service instead.&lt;/p&gt;
&lt;p&gt;For device removal, even though the physical device is no longer present, the
mapping may still remain, causing issues upon reinsertion. To resolve this, I
created a script to close the luks mapping upon device removal.&lt;/p&gt;
&lt;p&gt;Below are the systemd service and script files:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mount_enc_usb.sh:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-x

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$#&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;device&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nv"&gt;device_uuid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;blkid&lt;span class="w"&gt; &lt;/span&gt;--output&lt;span class="w"&gt; &lt;/span&gt;udev&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ID_FS_UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f2&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$device_uuid&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;000b2670-be4a-41b4-98eb-9adbd12a7616&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Found our device, let&amp;#39;s trigger systemd-cryptsetup&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;/usr/lib/systemd/systemd-cryptsetup&lt;span class="w"&gt; &lt;/span&gt;attach&lt;span class="w"&gt; &lt;/span&gt;GPG_USB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;tpm2-device&lt;span class="o"&gt;=&lt;/span&gt;auto
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;/media/vasudev/GPG_USB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/media/vasudev/GPG_USB/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;vasudev:vasudev&lt;span class="w"&gt; &lt;/span&gt;/media/vasudev/GPG_USB&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;/dev/mapper/GPG_USB&lt;span class="w"&gt; &lt;/span&gt;/media/vasudev/GPG_USB
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Not the interested device. Ignoring.&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;umount_enc_usb.sh:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$#&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;fsuuid&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;000b2670-be4a-41b4-98eb-9adbd12a7616&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Our device is removed, let&amp;#39;s close the luks mapping&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;/dev/mapper/GPG_USB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cryptsetup&lt;span class="w"&gt; &lt;/span&gt;luksClose&lt;span class="w"&gt; &lt;/span&gt;/dev/mapper/GPG_USB
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Not our device.&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;mount-gpg-usb&amp;#64;.service:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Mount the encrypted USB device service&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/mount_enc_usb.sh&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this setup, plugging in the USB device will automatically unseal and mount
it, and upon removal, the luks mapping will be closed.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;This can be even done for LUKS2 encrypted root disk but will need some
tweaking in initramfs.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://wiki.archlinux.org/title/Trusted_Platform_Module"&gt;Trusted Platform Module Arch Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.reddit.com/r/openSUSE/comments/oydwuz/unable_to_use_systemdcryptenroll/"&gt;systemd-cryptenroll issue with LUKS1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.baeldung.com/linux/shell-run-script-usb-plugged"&gt;Execute shell script when USB Device is plugged&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="systemd-cryptenroll"/><category term="systemd"/><category term="tpm2"/><category term="luks2"/><category term="mount"/></entry><entry><title>Migrating my domain from copyninja.info to copyninja.in</title><link href="https://copyninja.in/blog/migrating_domain.html" rel="alternate"/><published>2023-06-25T16:13:00+05:30</published><updated>2023-06-25T16:13:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2023-06-25:/blog/migrating_domain.html</id><summary type="html">&lt;p class="first last"&gt;Just an announcment about domain name move&lt;/p&gt;
</summary><content type="html">&lt;p&gt;After holding the domain &lt;em&gt;copyninja.info&lt;/em&gt; for almost 15 years, I finally let it
expire and bought a new domain, &lt;em&gt;copyninja.in&lt;/em&gt;. With this move, I also bid
goodbye to my VPS, which I had been using for over 12 years on DigitalOcean.
This particular VPS was initially set up with Debian Wheezy (7) and had been
upgraded over the years to successive Debian versions and finally was running
Debian Bullseye (11).&lt;/p&gt;
&lt;p&gt;The main reason for the move was that the &lt;em&gt;.info&lt;/em&gt; domain was becoming more
expensive every year, and the VPS, which I had upgraded to the $10 USD range,
cost around $12 USD per month with GST included. Since I wasn't really using the
VPS anymore and had recently even broken my DNS and mail server settings, I
decided it was the right time to reduce this additional cost.&lt;/p&gt;
&lt;p&gt;Now I have a cheaper &lt;em&gt;.in&lt;/em&gt; domain, and the VPS is on a minimal configuration at
DigitalOcean, costing $5 USD per month (which becomes almost $7 USD with GST).
Currently, I only run a blog and mail server on this VPS. I will assess if I
really need to keep running the mail server for some more time. If not, I will
move the blog to a hosting service like GitHub Pages and completely get rid of
the VPS.&lt;/p&gt;
&lt;p&gt;My email address has now changed, and the new mail can be obtained from this
&lt;cite&gt;link &amp;lt;http://scr.im/newcopyninj&amp;gt;&lt;/cite&gt;. I have updated my GPG key and added the new
email as the new UID. I still need to revoke the old domain UID. The key has
already been updated in the Debian Keyring.&lt;/p&gt;
</content><category term="misc"/><category term="domain"/><category term="move"/><category term="newdomain"/></entry><entry><title>Notes: Experimenting with ZRAM and Memory Over commit</title><link href="https://copyninja.in/blog/zram_memory_overcommit.html" rel="alternate"/><published>2023-06-20T10:55:00+05:30</published><updated>2023-06-20T10:55:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2023-06-20:/blog/zram_memory_overcommit.html</id><summary type="html">&lt;p class="first last"&gt;Notes on experiments with ZRAM and vm.overcommit_memory&lt;/p&gt;
</summary><content type="html">&lt;div class="section" id="introduction"&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The ZRAM module in the Linux kernel creates a memory-backed block device that
stores its content in a compressed format. It offers users the choice of
compression algorithms such as lz4, zstd, or lzo. These algorithms differ in
compression ratio and speed, with zstd providing the best compression but being
slower, while lz4 offers higher speed but lower compression.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="using-zram-as-swap"&gt;
&lt;h2&gt;Using ZRAM as Swap&lt;/h2&gt;
&lt;p&gt;One interesting use case for ZRAM is utilizing it as swap space in the system.
There are two utilities available for configuring ZRAM as swap: zram-tools and
systemd-zram-generator. However, Debian Bullseye lacks systemd-zram-generator,
making zram-tools the only option for Bullseye users. While it's possible to use
systemd-zram-generator by self-compiling or via cargo, I preferred using tools
available in the distribution repository due to my restricted environment.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="installation"&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;The installation process is straightforward. Simply execute the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;zram-tools
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="configuration"&gt;
&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The configuration involves modifying a simple shell script file
&lt;em&gt;/etc/default/zramswap&lt;/em&gt; sourced by the &lt;cite&gt;/usr/bin/zramswap&lt;/cite&gt; script. Here's an
example of the configuration I used:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# Compression algorithm selection&lt;/span&gt;
&lt;span class="c1"&gt;# Speed: lz4 &amp;gt; zstd &amp;gt; lzo&lt;/span&gt;
&lt;span class="c1"&gt;# Compression: zstd &amp;gt; lzo &amp;gt; lz4&lt;/span&gt;
&lt;span class="c1"&gt;# This is not inclusive of all the algorithms available in the latest kernels&lt;/span&gt;
&lt;span class="c1"&gt;# See /sys/block/zram0/comp_algorithm (when the zram module is loaded) to check&lt;/span&gt;
&lt;span class="c1"&gt;# the currently set and available algorithms for your kernel [1]&lt;/span&gt;
&lt;span class="c1"&gt;# [1]  https://github.com/torvalds/linux/blob/master/Documentation/blockdev/zram.txt#L86&lt;/span&gt;
&lt;span class="nv"&gt;ALGO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zstd

&lt;span class="c1"&gt;# Specifies the amount of RAM that should be used for zram&lt;/span&gt;
&lt;span class="c1"&gt;# based on a percentage of the total available memory&lt;/span&gt;
&lt;span class="c1"&gt;# This takes precedence and overrides SIZE below&lt;/span&gt;
&lt;span class="nv"&gt;PERCENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;

&lt;span class="c1"&gt;# Specifies a static amount of RAM that should be used for&lt;/span&gt;
&lt;span class="c1"&gt;# the ZRAM devices, measured in MiB&lt;/span&gt;
&lt;span class="c1"&gt;# SIZE=256000&lt;/span&gt;

&lt;span class="c1"&gt;# Specifies the priority for the swap devices, see swapon(2)&lt;/span&gt;
&lt;span class="c1"&gt;# for more details. A higher number indicates higher priority&lt;/span&gt;
&lt;span class="c1"&gt;# This should probably be higher than hdd/ssd swaps.&lt;/span&gt;
&lt;span class="c1"&gt;# PRIORITY=100&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I chose zstd as the compression algorithm for its superior compression
capabilities. Additionally, I reserved 30% of memory as the size of the zram
device. After modifying the configuration, restart the &lt;cite&gt;zramswap.service&lt;/cite&gt; to
activate the swap:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;zramswap.service
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="using-systemd-zram-generator"&gt;
&lt;h2&gt;Using systemd-zram-generator&lt;/h2&gt;
&lt;p&gt;For Debian Bookworm users, an alternative option is systemd-zram-generator.
Although zram-tools is still available in Debian Bookworm,
systemd-zram-generator offers a more integrated solution within the systemd
ecosystem. Below is an example of the translated configuration for
systemd-zram-generator, located at &lt;cite&gt;/etc/systemd/zram-generator.conf&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# This config file enables a /dev/zram0 swap device with the following
# properties:
# * size: 50% of available RAM or 4GiB, whichever is less
# * compression-algorithm: kernel default
#
# This device&amp;#39;s properties can be modified by adding options under the
# [zram0] section below. For example, to set a fixed size of 2GiB, set
# `zram-size = 2GiB`.

[zram0]
zram-size = ceil(ram * 30/100)
compression-algorithm = zstd
swap-priority = 100
fs-type = swap
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After making the necessary changes, reload systemd and start the &lt;cite&gt;systemd-zram-setup&amp;#64;zram0.service&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;daemon-reload
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;systemd-zram-setup@zram0.service
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;cite&gt;systemd-zram-generator&lt;/cite&gt; creates the zram device by loading the kernel
module and then creates a &lt;cite&gt;systemd.swap&lt;/cite&gt; unit to mount the zram device as swap.
In this case, the swap file is called &lt;cite&gt;zram0.swap&lt;/cite&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="checking-compression-and-details"&gt;
&lt;h2&gt;Checking Compression and Details&lt;/h2&gt;
&lt;p&gt;To verify the effectiveness of the swap configuration, you can use the &lt;cite&gt;zramctl&lt;/cite&gt;
command, which is part of the &lt;cite&gt;util-linux&lt;/cite&gt; package. Alternatively, the
&lt;cite&gt;zramswap&lt;/cite&gt; utility provided by &lt;cite&gt;zram-tools&lt;/cite&gt; can be used to obtain the same
output.&lt;/p&gt;
&lt;p&gt;During my testing with synthetic memory load created using &lt;em&gt;stress-ng&lt;/em&gt; &lt;em&gt;vm&lt;/em&gt;
class I found that I can reach upto &lt;em&gt;40%&lt;/em&gt; compression ratio.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="memory-overcommit"&gt;
&lt;h2&gt;Memory Overcommit&lt;/h2&gt;
&lt;p&gt;Another use case I was looking for is allowing the launching of applications
that require more memory than what is available in the system. By default, the
Linux kernel attempts to estimate the amount of free memory left on the system
when user space requests more memory (&lt;cite&gt;vm.overcommit_memory=0&lt;/cite&gt;). However, you
can change this behavior by modifying the sysctl value for
&lt;cite&gt;vm.overcommit_memory&lt;/cite&gt; to &lt;cite&gt;1&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;To demonstrate this, I ran a test using stress-ng to request more memory than
the system had available. As expected, the Linux kernel refused to allocate
memory, and the stress-ng process could not proceed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;free&lt;span class="w"&gt; &lt;/span&gt;-tg&lt;span class="w"&gt;                                                                                                                                                                                         &lt;/span&gt;──&lt;span class="o"&gt;(&lt;/span&gt;Mon,Jun19&lt;span class="o"&gt;)&lt;/span&gt;─┘
&lt;span class="w"&gt;                &lt;/span&gt;total&lt;span class="w"&gt;        &lt;/span&gt;used&lt;span class="w"&gt;        &lt;/span&gt;free&lt;span class="w"&gt;      &lt;/span&gt;shared&lt;span class="w"&gt;  &lt;/span&gt;buff/cache&lt;span class="w"&gt;   &lt;/span&gt;available
&lt;span class="w"&gt; &lt;/span&gt;Mem:&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Swap:&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Total:&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="m"&gt;41&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="m"&gt;19&lt;/span&gt;

sudo&lt;span class="w"&gt; &lt;/span&gt;stress-ng&lt;span class="w"&gt; &lt;/span&gt;--vm&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--vm-bytes&lt;span class="o"&gt;=&lt;/span&gt;50G&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="w"&gt;                                                                                                                                                      &lt;/span&gt;──&lt;span class="o"&gt;(&lt;/span&gt;Mon,Jun19&lt;span class="o"&gt;)&lt;/span&gt;─┘
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;setting&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;second&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mins,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.00&lt;span class="w"&gt; &lt;/span&gt;secs&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;per&lt;span class="w"&gt; &lt;/span&gt;stressor
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dispatching&lt;span class="w"&gt; &lt;/span&gt;hogs:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vm
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496312&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vm:&lt;span class="w"&gt; &lt;/span&gt;gave&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;trying&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;mmap,&lt;span class="w"&gt; &lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;available&lt;span class="w"&gt; &lt;/span&gt;memory,&lt;span class="w"&gt; &lt;/span&gt;skipping&lt;span class="w"&gt; &lt;/span&gt;stressor
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;warn:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vm:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496311&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;aborted&lt;span class="w"&gt; &lt;/span&gt;early,&lt;span class="w"&gt; &lt;/span&gt;out&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;resources
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vm:
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;warn:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;System&lt;span class="w"&gt; &lt;/span&gt;Management&lt;span class="w"&gt; &lt;/span&gt;Interrupts
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;passed:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;failed:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;skipped:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;vm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;stress-ng:&lt;span class="w"&gt; &lt;/span&gt;info:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1496310&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;successful&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;completed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.04s
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By setting &lt;cite&gt;vm.overcommit_memory=1&lt;/cite&gt;, Linux will allocate memory in a more relaxed
manner, assuming an infinite amount of memory is available.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;ZRAM provides disks that allow for very fast I/O, and compression allows for a
significant amount of memory savings. ZRAM is not restricted to just swap usage;
it can be used as a normal block device with different file systems.&lt;/p&gt;
&lt;p&gt;Using ZRAM as swap is beneficial because, unlike disk-based swap, it is faster,
and compression ensures that we use a smaller amount of RAM itself as swap
space.&lt;/p&gt;
&lt;p&gt;Additionally, adjusting the memory overcommit settings can be beneficial for
scenarios that require launching memory-intensive applications.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: When running stress tests or allocating excessive memory, be cautious
about the actual memory capacity of your system to prevent out-of-memory (OOM)
situations.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Feel free to explore the capabilities of ZRAM and optimize your system's memory
management. Happy computing!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="reference"&gt;
&lt;h2&gt;Reference&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.kernel.org/doc/html/latest/admin-guide/blockdev/zram.html"&gt;zram: Compressed RAM-based block device&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.kernel.org/doc/Documentation/vm/overcommit-accounting"&gt;Overcommit Accounting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.baeldung.com/linux/overcommit-modes"&gt;Linux Overcommit Modes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://wiki.archlinux.org/title/Zram"&gt;zram: Arch Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://wiki.debian.org/ZRam"&gt;zram: Debian Wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="zram"/><category term="vm"/><category term="overcommit"/><category term="debian"/></entry><entry><title>Installing Debian from GRML Live CD</title><link href="https://copyninja.in/blog/live_install_debian.html" rel="alternate"/><published>2022-12-12T12:35:00+05:30</published><updated>2022-12-12T12:35:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2022-12-12:/blog/live_install_debian.html</id><summary type="html">&lt;p class="first last"&gt;New experiment to install Debian from GRML Live boot&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I had bought a Thinkpad E470 laptop back in 2018 which was lying unused for
quite some time. Recently when I wanted to use it, I found that the keyboard is
not working, especially some keys and after some time the laptop will hang in
Lenovo boot screen. I came back to Bangalore almost after 2 years from my
hometown (WFH due to Covid) and thought it was the right time to get my laptop
back to normal working state. After getting the keyboard replaced I noticed that
1TB HDD is no longer fast enough for my taste!. I've to admit I never thought I
would start disliking HDD so quickly thanks to modern SSD based work laptops. So
as a second upgrade I got the HDD removed from my laptop and got a 240G SSD.
Yeah I know its reduction from my original size but I intend to continue using
my old HDD via USB SATA enclosure as an external HDD which can house the extra
data which I need to save.&lt;/p&gt;
&lt;p&gt;So now that I've a SSD I need to install Debian Unstable again on it and this is
where I tried something new. My colleague (name redacted on request) suggested
to me use GRML live CD and install Debian via &lt;em&gt;debootstrap&lt;/em&gt;. And after giving a
thought I decided to try this out. Some reason for going ahead with this are
listed below&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Debian Installer does not support a proper BTRFS based root file system. It
just allows btrfs as root but no subvolume support. Also I'm not sure about
the luks support with btrfs as root.&lt;/li&gt;
&lt;li&gt;I also wanted to give a try to systemd-boot as my laptop is UEFI capable and
I've slowly started disliking Grub.&lt;/li&gt;
&lt;li&gt;I really hate installing task-kde-desktop (Yeah you read it right, I've switched
to be a KDE user for quite some time) which will pull tons of unwanted stuff
and bloat. Well it's not just task-kde-desktop but any other task-desktop
package does similar and I don't want to have too much of unused stuff and
services running.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="disk-preparation"&gt;
&lt;h2&gt;Disk Preparation&lt;/h2&gt;
&lt;p&gt;As a first step I went to GRML website and downloaded &lt;a class="reference external" href="https://grml.org/download/prerelease/"&gt;current pre-release&lt;/a&gt;. Frankly, I'm using GRML for first
time and I was not sure what to expect. When I booted it up I was bit taken a
back to see its console based and I did not have a wired lan just a plain
wireless dongle (Jiofi device) and was wondering what it will take to connect.
But surprisingly curses based UI was pretty much straight forward to allow me to
connect to Wifi AP. Another thing was the rescue CD had non-free firmware as the
laptop was using ath10k device and needed non-free blobs to operate.&lt;/p&gt;
&lt;p&gt;Once I got shell prompt in rescue CD first thing I did was to reconfigure
console-setup to increase  font size which was very very small on default boot.
Once that is done I did the following to create a 1G (FAT32) partition for EFI.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;parted&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;optimal&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/dev/sda&lt;span class="w"&gt; &lt;/span&gt;mklabel&lt;span class="w"&gt; &lt;/span&gt;gpt
parted&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;optimal&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/dev/sda&lt;span class="w"&gt; &lt;/span&gt;mkpart&lt;span class="w"&gt; &lt;/span&gt;primary&lt;span class="w"&gt; &lt;/span&gt;vfat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;1G
parted&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;optimal&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/dev/sda&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;esp&lt;span class="w"&gt; &lt;/span&gt;on
mkfs.vfat&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;boot_disk&lt;span class="w"&gt; &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/sda1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So here is what I did: created a 1G vfat type partition and set the esp flag on
it. This will be mounted to /boot/efi for systemd-boot. Next I created a single
partition on the rest of the available free disk which will be used as the root
file system.&lt;/p&gt;
&lt;p&gt;Next I encrypted the root parition using LUKS and then created the BTRFS file
system on top of it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cryptsetup&lt;span class="w"&gt; &lt;/span&gt;luksFormat&lt;span class="w"&gt; &lt;/span&gt;/dev/sda2
cryptsetup&lt;span class="w"&gt; &lt;/span&gt;luksOpen&lt;span class="w"&gt; &lt;/span&gt;/dev/sda2&lt;span class="w"&gt; &lt;/span&gt;ENC
mkfs.btrfs&lt;span class="w"&gt; &lt;/span&gt;-L&lt;span class="w"&gt; &lt;/span&gt;root_disk&lt;span class="w"&gt; &lt;/span&gt;/dev/mapper/ENC
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next is to create subvolumes in BTRFS. I followed suggestion by colleague and
created a top-level &lt;em&gt;&amp;#64;&lt;/em&gt; as subvolume below which created &lt;em&gt;&amp;#64;/home&lt;/em&gt; &lt;em&gt;&amp;#64;/var/log&lt;/em&gt; &lt;em&gt;&amp;#64;/opt&lt;/em&gt; .
Also enabled compression with zstd and level of 1 to avoid battery drain.
Finally marked the &lt;em&gt;&amp;#64;&lt;/em&gt; as default subvolume to avoid adding it to fstab entry.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zstd:1&lt;span class="w"&gt; &lt;/span&gt;/dev/mapper/ENC&lt;span class="w"&gt; &lt;/span&gt;/mnt
btrfs&lt;span class="w"&gt; &lt;/span&gt;subvol&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;/mnt/@
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/@
btrfs&lt;span class="w"&gt; &lt;/span&gt;subvol&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;./home
btrfs&lt;span class="w"&gt; &lt;/span&gt;subvol&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;./opt
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;var
btrfs&lt;span class="w"&gt; &lt;/span&gt;subvol&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;./var/log
btrfs&lt;span class="w"&gt; &lt;/span&gt;suvol&lt;span class="w"&gt; &lt;/span&gt;set-default&lt;span class="w"&gt; &lt;/span&gt;/mnt/@
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="bootstrapping-debian"&gt;
&lt;h2&gt;Bootstrapping Debian&lt;/h2&gt;
&lt;p&gt;Now that root disk is prepared next step was to bootstrap the root file system.
I used debootstrap for this job. One thing I missed here from installer was
ability to preseed. I tried looking around to figure out if we can preseed
debootstrap but did not find much. If you know the procedure do point it to me.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/
debootstrap&lt;span class="w"&gt; &lt;/span&gt;--include&lt;span class="o"&gt;=&lt;/span&gt;dbus,locales,tzdata&lt;span class="w"&gt; &lt;/span&gt;unstable&lt;span class="w"&gt; &lt;/span&gt;@/&lt;span class="w"&gt; &lt;/span&gt;http://deb.debian.org/debian
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Well this just gets a bare minimal installation of Debian I need to install rest
of the things post this step manually by chroot into target folder &amp;#64;/.&lt;/p&gt;
&lt;p&gt;I like the &lt;strong&gt;grml-chroot&lt;/strong&gt; command for chroot purpose, it does most of the job of
mounting all required directory like /dev/ /proc /sys etc. But before entering
chroot I need to mount the ESP partition we created to &lt;strong&gt;/boot/efi&lt;/strong&gt; so that I
can finalize the installation of kernel and &lt;strong&gt;systemd-boot&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;umount&lt;span class="w"&gt; &lt;/span&gt;/mnt
mount&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zstd:1&lt;span class="w"&gt; &lt;/span&gt;/dev/mapper/ENC&lt;span class="w"&gt; &lt;/span&gt;/mnt
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/mnt/boot/efi
mount&lt;span class="w"&gt; &lt;/span&gt;/dev/sda1&lt;span class="w"&gt; &lt;/span&gt;/mnt/boot/efi
grml-chroot&lt;span class="w"&gt; &lt;/span&gt;/mnt&lt;span class="w"&gt; &lt;/span&gt;/bin/bash
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I remounted the root subvolume &lt;em&gt;&amp;#64;&lt;/em&gt; directly to /mnt now, remember I made &lt;em&gt;&amp;#64;&lt;/em&gt; as
default subvolume before. I also mounted ESP partition with FAT32 file system to
&lt;em&gt;/boot/efi&lt;/em&gt;. Finally I used grml-chroot to get into chroot of newly bootstrapped
file system.&lt;/p&gt;
&lt;p&gt;Now I will install the kernel and minimal KDE desktop installation and configure
locales and time zone data for the new system. I wanted to use dracut instead of
default initramfs-tools for initrd. I also need to install cryptsetup and
btrfs-progs so I can decrypt and really boot into my new system.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;update
apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;linux-image-amd64&lt;span class="w"&gt; &lt;/span&gt;dracut&lt;span class="w"&gt; &lt;/span&gt;openssh-client&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;kde-plasma-desktop&lt;span class="w"&gt; &lt;/span&gt;plasma-workspace-wayland&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;plasma-nm&lt;span class="w"&gt; &lt;/span&gt;cryptsetup&lt;span class="w"&gt; &lt;/span&gt;btrfs-progs&lt;span class="w"&gt; &lt;/span&gt;sudo
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next is setting up crypttab and fstab entries for new system. Following entry is
added to fstab&lt;/p&gt;
&lt;pre class="literal-block"&gt;
LABEL=&amp;quot;root_disk&amp;quot; / btrfs defaults,compress=zstd:1 0 0
&lt;/pre&gt;
&lt;p&gt;And the crypttab entry&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ENCRYPTED_ROOT UUID=xxxx none discard,x-initrd.attach
&lt;/pre&gt;
&lt;p&gt;I've not written actual UUID above this is just for the purpose of showing the
content of /etc/crypttab. Once these entries are added we need to recreate
initrd. I just reconfigured the installed kernel package for retriggerring the
recreation of initrd using dracut.
..
Reconfiguration was locales is done by editing /etc/locales.gen to uncomment
&lt;em&gt;en_US.UTF-8&lt;/em&gt; and writing /etc/timezone with &lt;em&gt;Asia/Kolkata&lt;/em&gt;. I used
&lt;em&gt;DEBIAN_FRONTEND=noninteractive&lt;/em&gt; to avoid another prompt asking for locale and
timezone information.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noninteractive
dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;locales
dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;tzdata
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Added my user using &lt;em&gt;adduser&lt;/em&gt; command and also set the root password as well.
Added my user to &lt;em&gt;sudo&lt;/em&gt; group so I can use sudo to elevate privileges.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="setting-up-systemd-boot"&gt;
&lt;h2&gt;Setting up systemd-boot&lt;/h2&gt;
&lt;p&gt;So now basic usable system is ready last part is enabling the systemd-boot
configuration as I'm not gonna use grub. I did following to install
systemd-boot. Frankly I'm not expert of this it was colleague's suggestion.&lt;/p&gt;
&lt;p&gt;Before installing the systemd-boot I had to setup kernel command line. This can
be done by writing command line to /etc/kernel/cmdline with following contents.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
systemd.gpt_auto=no quiet root=LABEL=root_disk
&lt;/pre&gt;
&lt;p&gt;I'm disabling systemd-gpt-generator to avoid race condition between crypttab
entry and auto generated entry by systemd. I faced this mainly because of my
stupidity of not adding entry &lt;em&gt;root=LABEL=root_disk&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;systemd-boot
bootctl&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--make-entry-directory&lt;span class="o"&gt;=&lt;/span&gt;yes&lt;span class="w"&gt; &lt;/span&gt;--entry-token&lt;span class="o"&gt;=&lt;/span&gt;machine-id
dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;linux-image-6.0.0-5-amd64
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally exit from the chroot and reboot into the freshly installed system.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;systemd-boot&lt;/em&gt; already ships a hook file &lt;em&gt;zz-systemd-boot&lt;/em&gt; under &lt;em&gt;/etc/kernel&lt;/em&gt;
so its pretty much usable without any manual intervention. Previously after
kernel installation  we had to manually update kernel image in efi partitions
using &lt;em&gt;bootctl&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclussion"&gt;
&lt;h2&gt;Conclussion&lt;/h2&gt;
&lt;p&gt;Though installing from live image is not new and debian-installer also does the
same only difference is more control over installation and doing things which is
installer is not letting you do (or should I say is not part of default
installation?). If properly automated using scripts we can leverage this to do
custom installation in large scale environments. I know there is FAI but I've
not explored it and felt there is too much to setup for a simple installations
with specific requirements.&lt;/p&gt;
&lt;p&gt;So finally I've a system with Debian which differs from default Debian
installation :-). I should thank my colleague for rekindling nerd inside me who
had stopped experimenting quite a long time back.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="debian"/><category term="live"/><category term="grml"/><category term="systemd-boot"/><category term="btrfs"/></entry><entry><title>Note to Self: Growing the Root File System on First Boot</title><link href="https://copyninja.in/blog/grow_rootfs.html" rel="alternate"/><published>2019-02-16T22:13:00+05:30</published><updated>2019-02-16T22:13:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2019-02-16:/blog/grow_rootfs.html</id><summary type="html">&lt;p class="first last"&gt;Post discusses about expanding root file system of a system to full
extent of available space in device.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;These 2 are the use cases I came across for expanding root file system.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;RaspberryPi images which comes in smaller image size like 1GB which you write
bigger size SD cards like 32GB but you want to use full 32GB of space when
system comes up.&lt;/li&gt;
&lt;li&gt;You have a VM image which is contains basic server operating system and you want
to provision the same as a VM with much larger size root file system.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My current use case was second but I learnt the trick from 1, that is the
&lt;a class="reference external" href="https://github.com/Debian/raspi3-image-spec"&gt;RaspberryPi3 image spec&lt;/a&gt; by
Debian project.&lt;/p&gt;
&lt;p&gt;Idea behind the expanding root file system is first expanding the root file
system to full available size and then run resize2fs on the expanded partition
to grow file system. &lt;em&gt;resize2fs&lt;/em&gt; is a tool specific for ext2/3/4 file system.
But this needs to be done before the file system is mounted.&lt;/p&gt;
&lt;p&gt;Here is my modified script from &lt;a class="reference external" href="https://github.com/Debian/raspi3-image-spec/blob/master/rpi3-resizerootfs"&gt;raspi3-image-spec repo&lt;/a&gt;.
Only difference is I've changed the logic of extracting root partition device to
my need, and of course added comments based on my understanding.&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
&lt;span class="ch"&gt;#!/bin/sh
&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Just extracts root partition and removes partition number to get the device
# name eg. /dev/sda1 becomes /dev/sda
&lt;/span&gt;&lt;span class="nv"&gt;roottmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;lsblk&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;NAME,MOUNTPOINT&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/$'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;rootpart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;roottmp&lt;/span&gt;&lt;span class="p"&gt;%% */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;rootdev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rootpart&lt;/span&gt;&lt;span class="p"&gt;%1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Use sfdisk to extend partition to all available free space on device.
&lt;/span&gt;flock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$rootdev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sfdisk&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$rootdev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-N&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF
,+
EOF&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Wait for all pending udev events to be handled
&lt;/span&gt;udevadm&lt;span class="w"&gt; &lt;/span&gt;settle&lt;span class="w"&gt;

&lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# detect the changes to partition (we extended it).
&lt;/span&gt;flock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$rootdev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;partprobe&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$rootdev&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# remount the root partition in read write mode
&lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;remount,rw&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$rootpart&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Finally grow the file system on root partition
&lt;/span&gt;resize2fs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$rootpart&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0fs
&lt;/pre&gt;
&lt;p&gt;raspi3-image-spec uses &lt;a class="reference external" href="https://github.com/Debian/raspi3-image-spec/blob/master/rpi3-resizerootfs.service"&gt;sytemd service&lt;/a&gt;
file to execute this script just before any file system is mounted. This is done
by a making service execute before &lt;em&gt;local-fs.pre&lt;/em&gt; target. From the man page for
&lt;em&gt;systemd.special&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;local-fs.target&lt;/dt&gt;
&lt;dd&gt;systemd-fstab-generator(3) automatically adds dependencies of type
Before= to all mount units that refer to local mount points for this
target unit. In addition, it adds dependencies of type Wants= to this
target unit for those mounts listed in /etc/fstab that have the auto
mount option set.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/blockquote&gt;
&lt;p&gt;Service also disables itself on executing to avoid re-runs on every boot. I've
used the service file from raspi3-image-spec as is.&lt;/p&gt;
&lt;div class="section" id="testing-with-vm"&gt;
&lt;h2&gt;Testing with VM&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;raspi3-image-spec&lt;/em&gt; is well tested, but I wanted to make sure this works with my
use case for VM. Since I didn't have any spare physical disks to experiment with
I used kpartx with raw file images. Here is what I did&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Created a stretch image using vmdb2 with grub installed. Image size is 1.5G&lt;/li&gt;
&lt;li&gt;I created another raw disk using fallocate of 4G size.&lt;/li&gt;
&lt;li&gt;I created a partition on 4G disk.&lt;/li&gt;
&lt;li&gt;Loop mounted the disk and wrote 1.5G image on it using dd&lt;/li&gt;
&lt;li&gt;Finally created a VM using virt-install  with this loop mounted device as
root disk.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below is my vmdb configuration yml again derived from &lt;a class="reference external" href="https://github.com/Debian/raspi3-image-spec/blob/master/raspi3.yaml"&gt;raspi3-image-spec&lt;/a&gt; one with
some modifications to suit my needs.&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="c1"&gt;# See https://wiki.debian.org/RaspberryPi3 for known issues and more details.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mkimg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;1.5G&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mklabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;msdos&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;device&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mkpart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;primary&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;device&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;0%&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;100%&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kpartx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mkfs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ext4&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;RASPIROOT&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;unpack-rootfs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;debootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;stretch&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;mirror&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;http://localhost:3142/deb.debian.org/debian&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;minbase&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;contrib&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;non-free&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;unless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;rootfs_unpacked&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# TODO(https://bugs.debian.org/877855): remove this workaround once&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# debootstrap is fixed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;chroot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;echo 'deb http://deb.debian.org/debian buster main contrib non-free' &amp;gt; /etc/apt/sources.list&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;apt-get update&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;unless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;rootfs_unpacked&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;install&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;parted&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;dosfstools&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;linux-image-amd64&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;unless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;rootfs_unpacked&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;grub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;bios&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache-rootfs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;unless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;rootfs_unpacked&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;echo &amp;quot;experimental&amp;quot; &amp;gt; &amp;quot;${ROOT?}/etc/hostname&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="no"&gt;# '..VyaTFxP8kT6' is crypt.crypt('raspberry', '..')&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;sed -i 's,root:[^:]*,root:..VyaTFxP8kT6,' &amp;quot;${ROOT?}/etc/shadow&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="no"&gt;sed -i 's,#PermitRootLogin prohibit-password,PermitRootLogin yes,g' &amp;quot;${ROOT?}/etc/ssh/sshd_config&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="no"&gt;install -m 644 -o root -g root fstab &amp;quot;${ROOT?}/etc/fstab&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="no"&gt;install -m 644 -o root -g root eth0 &amp;quot;${ROOT?}/etc/network/interfaces.d/eth0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="no"&gt;install -m 755 -o root -g root rpi3-resizerootfs &amp;quot;${ROOT?}/usr/sbin/rpi3-resizerootfs&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;install -m 644 -o root -g root rpi3-resizerootfs.service &amp;quot;${ROOT?}/etc/systemd/system&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;mkdir -p &amp;quot;${ROOT?}/etc/systemd/system/systemd-remount-fs.service.requires/&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;ln -s /etc/systemd/system/rpi3-resizerootfs.service &amp;quot;${ROOT?}/etc/systemd/system/systemd-remount-fs.service.requires/rpi3-resizerootfs.service&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="no"&gt;install -m 644 -o root -g root rpi3-generate-ssh-host-keys.service &amp;quot;${ROOT?}/etc/systemd/system&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;mkdir -p &amp;quot;${ROOT?}/etc/systemd/system/multi-user.target.requires/&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;ln -s /etc/systemd/system/rpi3-generate-ssh-host-keys.service &amp;quot;${ROOT?}/etc/systemd/system/multi-user.target.requires/rpi3-generate-ssh-host-keys.service&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;rm -f ${ROOT?}/etc/ssh/ssh_host_*_key*&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nt"&gt;root-fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Clean up archive cache (likely not useful) and lists (likely outdated) to&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# reduce image size by several hundred megabytes.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;chroot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;apt-get clean&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;rm -rf /var/lib/apt/lists&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# TODO(https://github.com/larswirzenius/vmdb2/issues/24): remove once vmdb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# clears /etc/resolv.conf on its own.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;rm &amp;quot;${ROOT?}/etc/resolv.conf&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;root-fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I could not run with vmdb2 installed from Debian archive, so I cloned
raspi3-image-spec and used vmdb2 submodule from it. And here are rest of
commands used for testing the script.&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
fallocate&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;4G&lt;span class="w"&gt; &lt;/span&gt;rootdisk.img&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Create one partition with full disk
&lt;/span&gt;sfdisk&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;rootdisk.img&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF
,+
EOF&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;kpartx&lt;span class="w"&gt; &lt;/span&gt;-av&lt;span class="w"&gt; &lt;/span&gt;rootdisk.img&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# mounts on /dev/loop0 for me
&lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vmdb.img&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/loop0&lt;span class="w"&gt;
&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;virt-install&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;experimental&lt;span class="w"&gt; &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--disk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/loop0&lt;span class="w"&gt; &lt;/span&gt;--controller&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scsi,model&lt;span class="o"&gt;=&lt;/span&gt;virtio-scsi&lt;span class="w"&gt; &lt;/span&gt;--boot&lt;span class="w"&gt; &lt;/span&gt;hd&lt;span class="w"&gt; &lt;/span&gt;--network&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bridge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lxcbr0
&lt;/pre&gt;
&lt;p&gt;Once VM booted I could see the root file system is 4G of size instead of 1.5G it
was after using dd to write image on to it. So success!.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="resize2fs"/><category term="notetoself"/></entry><entry><title>SPAKE2 in Golang: Implementing Groups</title><link href="https://copyninja.in/blog/golang_spake2_5.html" rel="alternate"/><published>2018-09-02T17:14:00+05:30</published><updated>2018-09-02T17:14:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-09-02:/blog/golang_spake2_5.html</id><summary type="html">&lt;p class="first last"&gt;Fifth post in &amp;quot;SPAKE2 in Golang&amp;quot; series. This post is my
implementation notes for groups in Golang&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my &lt;a class="reference external" href="https://copyninja.info/blog/golang_spake2_4.html"&gt;previous post&lt;/a&gt; I
talked about SPAKE2 protocol and Ed25519 Curve group. This post is mostly
implementation notes and decisions taken during implementing EC groups and
number groups in Golang.&lt;/p&gt;
&lt;div class="section" id="in-the-beginning"&gt;
&lt;h2&gt;In the Beginning ...&lt;/h2&gt;
&lt;p&gt;Like always I had too many question on how to do? what to do? etc. etc. Well
there is no definitive answer, you have to experiment to get the answer. So as a
first step I had to decide what I need. Looking at Python implementation of
SPAKE2 some basic group operations needed are as follows.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Element Addition for the group&lt;/li&gt;
&lt;li&gt;Scalar Multiplication for the group&lt;/li&gt;
&lt;li&gt;Scalar Multiplication with Base point/Generator of group&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Along with this some other functions are needed, these are not exactly group
related operations, but are needed in SPAKE2 calculation. We can call them
helper operations and they are listed as follows.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Convert password into Scalar of the group (Scalar is nothing but big integer
in the group)&lt;/li&gt;
&lt;li&gt;Generate a Random scalar for the group.&lt;/li&gt;
&lt;li&gt;Constants M, N and S.&lt;/li&gt;
&lt;li&gt;Converting group element to bytes and creating element from bytes.&lt;/li&gt;
&lt;li&gt;Element Size for the group.&lt;/li&gt;
&lt;li&gt;Order of the subgroup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you might be wondering what &lt;cite&gt;S&lt;/cite&gt; might be, as I only talked about &lt;cite&gt;M&lt;/cite&gt; and &lt;cite&gt;N&lt;/cite&gt;
while explaining SPAKE2. This is for a special mode called &lt;strong&gt;Symmetric
Mode&lt;/strong&gt;. This special mode created by Brian Warner with help from other
cryptographic folks for &lt;strong&gt;magic-wormhole&lt;/strong&gt; use case. This mode removes the
side/identity from the SPAKE2 protocol as we saw in previous post (A, B) and
makes both side identical. This will reduce additional exchanges that had to be
done to setup side/identities for both peers.&lt;/p&gt;
&lt;p&gt;Next question was whether SPAKE2 implementation is going to be Ed25519 group
specific or whether I plan to introduce other groups as well?. This was
important decision I had to make, since Python version also has some integer
groups I decided to make groups configurable in Golang as well with Ed25519 as
default group.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="defining-group-interface"&gt;
&lt;h2&gt;Defining Group Interface&lt;/h2&gt;
&lt;p&gt;To make group as configurable in SPAKE2 package I had to define a generic type.
Though Golang does not have generics, we can define &lt;em&gt;interface type&lt;/em&gt; to get some
flexibility. As a first try I defined &lt;strong&gt;Group&lt;/strong&gt; interface as follows&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ConstM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ConstN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ConstS&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;RandomScalar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;PasswordToScalar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;ElementToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ElementFromBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;BasePointMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ScalarMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;ElementSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Remember this was not final version which I reached but initial version. I kept
this under &lt;cite&gt;group.go&lt;/cite&gt; file. I also thought it would be better to keep group
implementations outside SPAKE2. So I created SPAKE2 as
&lt;cite&gt;salsa.debian.org/vasudev/gospake2&lt;/cite&gt; Ed25519 group operations under
&lt;cite&gt;salsa.debian.org/vasudev/ed25519group&lt;/cite&gt; and integergroup operations under
&lt;cite&gt;salsa.debian.org/vasudev/integergroup&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;I hit my first road block with this representation. I created a type &lt;cite&gt;Ed25519&lt;/cite&gt;
in &lt;cite&gt;ed25519group&lt;/cite&gt; package and implemented the &lt;cite&gt;Group&lt;/cite&gt; interface above but
instead of function accepting/returning &lt;cite&gt;Group&lt;/cite&gt; I used &lt;cite&gt;Ed25519&lt;/cite&gt;. This felt
natural to me as &lt;cite&gt;Ed25519&lt;/cite&gt; was confimring to &lt;cite&gt;Group&lt;/cite&gt; interface but that Go
compiler thought otherwise. Go compiler refused to agree &lt;cite&gt;Ed25519&lt;/cite&gt; type
implemented &lt;cite&gt;Group&lt;/cite&gt; interface and told the defintion of functions do not match.
For eg. it said for ConstM, &lt;strong&gt;expected return value of Group but found
Ed25519&lt;/strong&gt;. I did not yet figure out why this does not work, but as far as I can
understand this happens because when Go compiler scans ConstM line it still does
not know that type &lt;cite&gt;Ed25519&lt;/cite&gt; implements &lt;cite&gt;Group&lt;/cite&gt; interface. I could have asked in
forums but frankly I did not know how to phrase this question :). If you are a
gopher and know the answer please do let me know :).&lt;/p&gt;
&lt;p&gt;Without spending too much time to figure out why its not working, I changed the
interface definition to look like below.&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ConstM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ConstN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ConstS&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;RandomScalar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;PasswordToScalar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;ElementToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ElementFromBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;BasePointMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;ScalarMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;

       &lt;/span&gt;&lt;span class="nx"&gt;ElementSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;So now compiler is happy because &lt;cite&gt;interface{}&lt;/cite&gt; means any type. Though I was not
happy because I had to do lot of type assertions in the actual implementation of
group.&lt;/p&gt;
&lt;p&gt;After I did first version of ed25519group and successfuly used it in gospake2
0.1.0, I was feeling something was not correct and things needs to be improved.
Then when I started to implement &lt;cite&gt;integergroup&lt;/cite&gt; package things started becoming
more clear to me. I finished writing &lt;cite&gt;integergroup&lt;/cite&gt; with same interface
definition as above.&lt;/p&gt;
&lt;p&gt;After both groups are implemented and integrated into gospake2, I started to
look at python code moe carefully. A pattern started emerging in my mind. Python
code was structured to differentiate Group and its elements, and this seemed
natural separation. Once you separat Elements your interface definition will
become more simpler.&lt;/p&gt;
&lt;p&gt;So after struggling a bit I wrote a new interface, now differentiating Elements
and Group itself. The final code as of writing this post is below.&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="c1"&gt;// Element represents the operation that needs to be satisfied by Group element.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;ScalarMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;Negate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;// Group defines methods that needs to be implemented by the number / elliptic&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// curve group which is used to implement SPAKE2 algorithm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="c1"&gt;// These functions are not really group operations but they are needed&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="c1"&gt;// to get the required group Element's needed for calculation of SPAKE2&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;ConstM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;ConstN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;ConstS&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="c1"&gt;// This operation is needed to get a random integer in the group&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;RandomScalar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="c1"&gt;// This operation is for converting user password to a group element&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;PasswordToScalar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="c1"&gt;// These operations are group operations&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;BasePointMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;ScalarMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="nx"&gt;ElementToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;ElementFromBytes&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="c1"&gt;// This operation should return size of the group&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;ElementSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="c1"&gt;// This operation returns order of subgroup&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Element interface requires implementer to implement &lt;cite&gt;Add&lt;/cite&gt;, &lt;cite&gt;ScalarMult&lt;/cite&gt; and
&lt;cite&gt;Negate&lt;/cite&gt; function. Group interface also has &lt;cite&gt;Add&lt;/cite&gt; and &lt;cite&gt;ScalarMult&lt;/cite&gt; operation but
Group functions require you to pass Element as input and returns Element as
output. Though it may be redundant it gives a natural organization to code.&lt;/p&gt;
&lt;p&gt;With new interface new group implementations don't have to do too much type
assertions but there will still be some which can't be avoided (eg. Element to
actual type).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="packages-subpackages-and"&gt;
&lt;h2&gt;Packages, Subpackages and....&lt;/h2&gt;
&lt;p&gt;Well there is no such thing called subpackage in Go, this is one of the learning
I had while writing &lt;em&gt;gospake2&lt;/em&gt; and related &lt;em&gt;group&lt;/em&gt; implementation. I first
created the &lt;em&gt;Group&lt;/em&gt; interface in file called &lt;cite&gt;group.go&lt;/cite&gt; which was under
&lt;cite&gt;salsa.debian.org/vasudev/gospake2&lt;/cite&gt; package. So to refer Group interface I just
need to import gospake2 and refer it as &lt;cite&gt;gospake2.Group&lt;/cite&gt;. In the beginning this
seemed correct approach as I did not directly refer the &lt;cite&gt;Group&lt;/cite&gt; interface in the
first versions of &lt;cite&gt;ed25519group&lt;/cite&gt; and &lt;cite&gt;integergroup&lt;/cite&gt;. (The version where I used
&lt;cite&gt;interface{}&lt;/cite&gt; extensively). But when I refactored to have 2 interfaces above I
got cyclic dependency error. ed25519group and integergroup both referred
gospake2.Group and gospake2 referred these groups.&lt;/p&gt;
&lt;p&gt;So to fix the error I moved the interface declaration from &lt;em&gt;group.go&lt;/em&gt; to
&lt;em&gt;groups&lt;/em&gt; folder under gospake2 package, and made it package &lt;em&gt;groups&lt;/em&gt;. Few
points I learned while doing this is&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Even if the package is inside your package you can't directly use it. i.e.
there is no such thing as subpackage. gospake2 had to refer groups with its
full namespace i.e. &lt;cite&gt;salsa.debian.org/vasudev/gospake2/groups&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Folder structure inside package does not directly relate to each other, its
just placing them in meaningful path like &lt;cite&gt;crypto/sha256&lt;/cite&gt; and &lt;cite&gt;crypto/sha512&lt;/cite&gt;
they do not mean they are related its just that they fall under cryptography.&lt;/li&gt;
&lt;li&gt;Standard library can refer to interface in parent package, for example
&lt;cite&gt;crypto/ecdsa&lt;/cite&gt; can refer to &lt;cite&gt;crypto.SignerOpts&lt;/cite&gt; interface which is defined in
crypto package just by importing &amp;quot;crypto&amp;quot; inside ecdsa package. This works
because &lt;em&gt;crypto&lt;/em&gt; is package name in GOPATH, but there is nothing special here.
For us to refer something in so called parent package we need to use fullpath
for example &lt;cite&gt;salsa.debian.org/vasudev/gospake2/groups&lt;/cite&gt; because that is how
user packages are namespaced under GOPATH.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So finally I got a proper layout for &lt;cite&gt;Group&lt;/cite&gt; and &lt;cite&gt;Element&lt;/cite&gt; interfaces, its now
available under &lt;cite&gt;salsa.debian.org/vasudev/gospake2/groups&lt;/cite&gt; package. If you
intend to provide a new group implementation for gospake2 you need to implement
these interfaces in your package.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="implementing-ed25519-group"&gt;
&lt;h2&gt;Implementing Ed25519 Group&lt;/h2&gt;
&lt;p&gt;Implementing Ed25519 group was a bit of adventurous journey. First I searched
for ready made implementation if any. Only thing I found was
&lt;cite&gt;golang.org/x/crypto/ed25519/internal/edwards25519&lt;/cite&gt; which is port of DJB's
original C code to Go by Adam Langley. Problem was this package was
internal to &lt;cite&gt;ed25519&lt;/cite&gt; package and Go compiler would refuse to allow you import it
outside the ed25519 package. So I decided to embed &lt;em&gt;edwards25519&lt;/em&gt; as a internal
package with in &lt;cite&gt;gospake2&lt;/cite&gt;. This was prior to second version of &lt;cite&gt;Group&lt;/cite&gt; interface
design.&lt;/p&gt;
&lt;p&gt;Even with embedding I could not really use it properly. I could get the
BasePointMult operation working but nothing else worked and naively I tried to
use &lt;cite&gt;ScMulAdd&lt;/cite&gt; for Scalar multiplication which was really a wrong thing to do.
Later I understood that the module was specifically written for Ed25519
signature scheme. Though it might still be possible to use it now that I've
understood the basics of curve, I will definitely give it a second try at later
point in time.&lt;/p&gt;
&lt;p&gt;After the failed attempt with edwards25519 Ramakrishnan suggested me to use big
integer and implement those methods myself and finally that is what I did. I
used &lt;cite&gt;math/big&lt;/cite&gt; package to implement the operations required myself. So the
experience of writing this module taught me a lot. Below are few of my
learnings.&lt;/p&gt;
&lt;div class="section" id="annoyance-with-big-int"&gt;
&lt;h3&gt;Annoyance with big.Int&lt;/h3&gt;
&lt;p&gt;While using big.Int I was annoyed by the specific syntax which invovled invoking
the operation using a big.Int variable which will set the result to same
variable and additionally return same value also. This design felt redundant to
me and also I had to create so many intermediate variables to get operations
like Add or Double implemented. Are you thinking why?. Then look at below
formula for Add to add 2 points &lt;cite&gt;P1 = (X1,Y1,T1,Z1)&lt;/cite&gt; and &lt;cite&gt;P2 = (X2, Y2, T2. Z2)&lt;/cite&gt;&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;X1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;X2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;X1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Y2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;X2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;T2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Z1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Z2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;X3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Y3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;T3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Z3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;With big.Int I had to create every intermediate variable and then calculate
their result, for eg. (Y1-X1) and (Y2 - X2) and then finally calculate A. At
this point I started liking C++ more as it will allow me to override + operator
;-). But at later point I noticed some Go code where people dealt with the
big.Int in following format&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="nx"&gt;Y1MX1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Y1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;X1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Y2MX2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Y2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;X2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Mul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Y1MX1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Y2MX2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It reduced intermediate variables to some extent, additionally it avoids
declaring required variables first and then use it. But still its bit of
annoyance :).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="confusions-with-pointers"&gt;
&lt;h3&gt;Confusions with Pointers&lt;/h3&gt;
&lt;p&gt;When using local variables of type big.Int and returning a pointer to
it, I started to have a doubt that if what I'm doing is correct. Being from C
background where you are not supposed to be returning pointer to a stack
variable, Go's ability to return address of local variable confused me. But it
looks like &lt;a class="reference external" href="https://stackoverflow.com/questions/38234487/go-returning-a-pointer-on-stack#38234526"&gt;Go compiler is smarter in this aspect&lt;/a&gt;.
Basically Go compiler does escape analysis to figure out if variable leaves
after function and if so it moves it to garbage collected heap. So basically as
Go programmer I need not bother on where my variables are allocated. Thats a
relief :).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="type-aliasing-in-go"&gt;
&lt;h3&gt;Type Aliasing in Go&lt;/h3&gt;
&lt;p&gt;Type aliasing in languages like Rust or C++ is a handy way to create alternate
name for previously created type. This just creates a new name for existing type
and you can still use the original types methods or variables. But this is not
the same case in Go. Go &lt;a class="reference external" href="https://golang.org/ref/spec#Type_declarations"&gt;language spec&lt;/a&gt;. clearly says that new type
does not derive anything from originl type. But compiler allows you to cast
to-and-fro from original to new type and vice versa.&lt;/p&gt;
&lt;p&gt;I was bit by this as I did not knew about it. I created a alias for
ExtendedPoint type as Ed25519 to implement Group interface. But when I tried to
access original functions from ExtendedPoint I noticed this behavior. So I had
to write private conversion function just to cast types around.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="implementing-scalar-multiplication-and-stack-exhaustion"&gt;
&lt;h3&gt;Implementing Scalar Multiplication and stack exhaustion&lt;/h3&gt;
&lt;p&gt;Implementing scalar multiplication was one of the last adventure I tackled in
the ed25519 group implementation. Scalar multiplication is multiplying a given
elliptic curve point with a large integer (otherwise called as scalar) limited
by subgroup order. Warner's python implementation was as follows&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scalarmult_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;# extended-&amp;gt;extended&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="c1"&gt;# This form only works properly when given points that are a member of&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="c1"&gt;# the main 1*L subgroup. It will give incorrect answers when called with&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="c1"&gt;# the points of order 1/2/4/8, including point Zero. (it will also work&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="c1"&gt;# properly when given points of order 2*L/4*L/8*L)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;xform_affine_to_extended&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;double_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scalarmult_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_add_elements_nonunfied&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Though I don't exactly remember first version of my scalar multiplication
function, it was mimicking the python code in Go with big.Int. The code worked
well with small integers but when I gave big numbers generated using
&lt;cite&gt;RandomScalar&lt;/cite&gt; function of &lt;cite&gt;Group&lt;/cite&gt; interface, code will panic as it will run out
of stack.&lt;/p&gt;
&lt;p&gt;Above python code is slightly optimized version, so I looked at Haskell
implementation of SPAKE2 which looked like below&lt;/p&gt;
&lt;pre class="code haskell literal-block"&gt;
&lt;span class="c1"&gt;-- | Scalar multiplication parametrised by addition.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nf"&gt;scalarMultiplyExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;::&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nf"&gt;scalarMultiplyExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;extendedZero&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nf"&gt;scalarMultiplyExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;even&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doubleExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scalarMultiplyExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;panic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Unexpected negative multiplier: &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;otherwise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scalarMultiplyExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;So algorithm is like this&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;If scalar is 1 return same point&lt;/li&gt;
&lt;li&gt;If scalar is 0 return identity element for group&lt;/li&gt;
&lt;li&gt;If scalar is even then recursively call scalarmult by reducing the scalar to
half and double the result.&lt;/li&gt;
&lt;li&gt;Otherwise recursively scalarmultiply the point with scalar reduced by 1 and
add the result to the point.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It might look slightly confusing explanation so I will just show the code below.&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ScalarMultSlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Zero&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IsEven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="c1"&gt;// If scalar is even we recursively call scalarmult with n/2 and&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="c1"&gt;// then double the result.&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ScalarMultSlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Rsh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="c1"&gt;// We decrement the scalar and recursively call scalarmult with&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="c1"&gt;// it then we add the result with point&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ScalarMultSlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AddUnified&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;So instead of dividing by 2 I just right shift the scalar by 1 which is faster
operation. (AddUnified  is one of the algorithm for point addition which is more
safer but slower alternative, hence the name ScalarMultSlow.)&lt;/p&gt;
&lt;p&gt;So this implementation works with every input, except the negative one for which
I modified ScalarMult definition in Group level to reduce input scalar to
subgroup order L. Otherwise Group function just calls function from Element.
Code below.&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="c1"&gt;// ScalarMult multiples given point with scalar and returns the result&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ed25519&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ScalarMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="c1"&gt;// First let's reduce s to curve order, this is important in case if we&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="c1"&gt;// pass negated value&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Zero&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="nx"&gt;extendedPoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;ExtendedPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;extendedPoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ScalarMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Probably I shoud move reducing the scalar to subgroup order into scalarmult
inside Element's implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="implementing-integer-group"&gt;
&lt;h2&gt;Implementing Integer Group&lt;/h2&gt;
&lt;p&gt;Given the problems I faced and things I learnt, implementing Ed25519 group,
implementing integer group was much straight forward. Only some design decisions
had to be made.&lt;/p&gt;
&lt;div class="section" id="how-to-represent-group-and-elements"&gt;
&lt;h3&gt;How to Represent Group and Elements&lt;/h3&gt;
&lt;p&gt;Unlike Ed25519 where group elements are basically points on the curve, element
in multiplicative integer groups are basically integers. So how do I represent
various integer groups?. Various integer groups are differentiated by bit length
of elements in it, group and subgroup order. Looking at python code I created a
structure called &lt;cite&gt;GroupParameters&lt;/cite&gt; which will contain necessary information for
a given group.&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;GroupParameters&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;elementSizeBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elementSizeBits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;scalarSize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I did not want to export these fields as they are not useful outside the
package. Python code implemented 3 integer group of 1024,2048 and 3072 bit
integers. All values for above variables were taken from &lt;a class="reference external" href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf"&gt;NIST document&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In first iteration I only had a struct called &lt;cite&gt;IntegerGroup&lt;/cite&gt; which had
parameters as member and implemented &lt;cite&gt;Group&lt;/cite&gt; interface from gospake2. But when I
refactored Group interface to have Element interface refactoring the code for
integergroup became bit challenging. I introduced &lt;cite&gt;IntegerElement&lt;/cite&gt; struct to
hold actual integer value, but since all operations needed access to order of
group I had to modify it to also contain parameters defined above. So final
definition of &lt;cite&gt;IntegerGroup&lt;/cite&gt; and &lt;cite&gt;IntegerElement&lt;/cite&gt; is as follows&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IntegerGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;GroupParameters&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IntegerElement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;GroupParameters&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Operations in &lt;cite&gt;IntegerGroup&lt;/cite&gt; were simply calling functions from
&lt;cite&gt;IntegerElement&lt;/cite&gt;. So its really redundant but to make sure I can distinguish
between both group and its element I had to use it in this form.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="scalar-multiplication-and-addition-operations"&gt;
&lt;h3&gt;Scalar Multiplication and Addition Operations&lt;/h3&gt;
&lt;p&gt;Since the integer groups are really multiplicative group, addition operation is
really a multiplication modulo p. Scalar multiplication is just exponentiation
modulo p. Since these operations are readily available in &lt;cite&gt;math/big&lt;/cite&gt; I did not
had to do anything much for integer group. These operations in &lt;cite&gt;IntegerElement&lt;/cite&gt;
are defined as follows.&lt;/p&gt;
&lt;pre class="code go literal-block"&gt;
&lt;span class="c1"&gt;// Add is actually multiplication mod `p` where `p` is order of the&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// multiplicative group&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IntegerElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;IntegerElement&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;IntegerElement&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
             &lt;/span&gt;&lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;You can't add elements of 2 different groups&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Mul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IntegerElement&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;// ScalarMult for multiplicative group is g^s mod p where `g` is group generator&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// and p is order of the group&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IntegerElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ScalarMult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nx"&gt;reducedS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IntegerElement&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reducedS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclussion"&gt;
&lt;h2&gt;Conclussion&lt;/h2&gt;
&lt;p&gt;Well its been already a pretty long post, so without extending it more I would
like to say that I had lot of learning experience in writing the Go code to
implement these integer and ed25519 group. Main learnings were&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;There is no definite answer for any questions, may it be how to write a
library or if I structured my library correctly. Of course there will be some
best practice available but you have to start at some point and then improve
it in iteration.&lt;/li&gt;
&lt;li&gt;Go provides great tooling especially linters and formatters which makes you
write a clean code. And also document all your exported functions as you
write (else you will keep seeing warnings in your editor which is annoying).&lt;/li&gt;
&lt;li&gt;Use your library yourself and you will see how you can improve it. If you are
feeling uncomfortable with your own written API then that means others will
too :).&lt;/li&gt;
&lt;li&gt;Every language is designed for a specific purpose, if I'm feeling discomfort
using some features of the language (I had problems with verbose error
handling) then probably I'm less experienced with language and should see how
others handle such things. There are many good projects which you can refer
to and lern from.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the next post which should be last in series I will write about design
decisions I made writing gospake2 package. Code for both ed25519 and integer
groups are now merged into gospake2 as that is the right place for them. You can
find the code for them in my &lt;a class="reference external" href="https://salsa.debian.org/vasudev/gospake2"&gt;gospake2 repo&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</content><category term="development"/><category term="go"/><category term="golang"/><category term="spake2"/><category term="cryptography"/></entry><entry><title>SPAKE2 in Golang: ECDH, SPAKE2 and Curve Ed25519</title><link href="https://copyninja.in/blog/golang_spake2_4.html" rel="alternate"/><published>2018-08-28T20:25:00+05:30</published><updated>2018-08-28T20:25:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-08-28:/blog/golang_spake2_4.html</id><summary type="html">&lt;p class="first last"&gt;Fourth post in SPAKE2 in Golang series. This post is my notes on
ECDH, SPAKE2 and curve Edwards25519 group&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my &lt;a class="reference external" href="https://copyninja.info/blog/golang_spake2_3.html"&gt;previous post&lt;/a&gt;  I
talked about finite field and how it helps in &lt;em&gt;Elliptic Curve Cryptography&lt;/em&gt;. In
this post we will see briefly how Diffie-Hellmann key exchange varies with use
of &lt;em&gt;Elliptic curve&lt;/em&gt; groups, then we will see SPAKE2 original variant followed by
Elliptic curve version and finally we will have a look at curve Ed25519 which is
used as default group in &lt;em&gt;python-spake2&lt;/em&gt; module.&lt;/p&gt;
&lt;div class="section" id="elliptic-curve-diffie-hellman-ecdh"&gt;
&lt;h2&gt;Elliptic Curve Diffie-Hellman (ECDH)&lt;/h2&gt;
&lt;p&gt;In the previous post we defined the domain parameter of elliptic curve
cryptography as &lt;span class="math"&gt;\((p, a, b, G, n, h)\)&lt;/span&gt;. Now we will see how we use this in
Diffie-Hellman Key exchange.&lt;/p&gt;
&lt;p&gt;Diffie-Hellman key exchange is a way to securely exchange cryptographic key over
public channel. Original Diffie-Hellman protocol used &lt;strong&gt;multiplicative group of
integers modulo p&lt;/strong&gt; where &lt;cite&gt;p&lt;/cite&gt; is the a large prime and &lt;cite&gt;g&lt;/cite&gt; a generator for
subgroup (as we saw in earlier post). The protocol can be explained as follows&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Alice and Bob agrees on &lt;cite&gt;p&lt;/cite&gt; and &lt;cite&gt;g&lt;/cite&gt; belonging to group &lt;cite&gt;G&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Alice selects &lt;cite&gt;a&lt;/cite&gt; belonging to &lt;cite&gt;G&lt;/cite&gt; and calculates &lt;span class="math"&gt;\(A = g^a \bmod{p}\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Bob selects &lt;cite&gt;b&lt;/cite&gt; belonging to &lt;cite&gt;G&lt;/cite&gt; and calculates &lt;span class="math"&gt;\(B = g^b \bmod{p}\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Alice sends Bob &lt;cite&gt;A&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Bob sends Alice &lt;cite&gt;B&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Now Alice calculates &lt;span class="math"&gt;\(s = B^a \bmod{p}\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Now Bob calculates &lt;span class="math"&gt;\(s = A^b \bmod{p}\)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Mathematically &lt;cite&gt;s&lt;/cite&gt; computed by both Alice and  Bob are same and hence both
share a shared secret now.&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
s = B^a \bmod{p} = g^{ba} \bmod{p} = A^b \bmod{p} = g^{ab} \bmod{p}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;Since group is Abelian &lt;span class="math"&gt;\(g^{ba} \bmod{p} = g^{ab} \bmod{p}\)&lt;/span&gt; and hence both
side will come to same shared key.&lt;/p&gt;
&lt;p&gt;Now in ECC,&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;private key &lt;span class="math"&gt;\(d\)&lt;/span&gt; is a random integer choosen from &lt;span class="math"&gt;\(\{1, \dots, n -
1\}\)&lt;/span&gt; where &lt;cite&gt;n&lt;/cite&gt; is the order of subgroup&lt;/li&gt;
&lt;li&gt;public key is the point &lt;span class="math"&gt;\(H = dG\)&lt;/span&gt; where &lt;cite&gt;G&lt;/cite&gt; is the base point of
subgroup.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With above now we can write Diffie-Hellman key exchange as&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Alice selects private key &lt;span class="math"&gt;\(d_A\)&lt;/span&gt; and public key &lt;span class="math"&gt;\(H_A = d_AG\)&lt;/span&gt; and
sends it to Bob&lt;/li&gt;
&lt;li&gt;Bob selects private key &lt;span class="math"&gt;\(d_B\)&lt;/span&gt; and public key &lt;span class="math"&gt;\(H_B = d_BG\)&lt;/span&gt; and
sends it to Alice&lt;/li&gt;
&lt;li&gt;Alice calculates &lt;span class="math"&gt;\(S = d_AH_B\)&lt;/span&gt; and Bob calculates &lt;span class="math"&gt;\(S = d_BH_A\)&lt;/span&gt;
which if you see carefully is one and same and Alice and Bob now share a
secret key!.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="math"&gt;
\begin{equation*}
S = d_A H_B = d_A (d_B G) = d_B (d_A G) = d_B H_A
\end{equation*}
&lt;/div&gt;
&lt;p&gt;In both cases observer only sees the public key and will not be able to find
discrete logarithm (hard problem), given the numbers are large prime.&lt;/p&gt;
&lt;p&gt;Advantage of ECDH is its faster as its replacing the costly exponentiation
operation with &lt;em&gt;scalar multiplication&lt;/em&gt; without reducing hardness of the problem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="spake2-protocol"&gt;
&lt;h2&gt;SPAKE2 Protocol&lt;/h2&gt;
&lt;p&gt;Now that we understood Diffie-Hellman exchange and saw how to apply Elliptic
curve in Diffie-Hellman exchange, lets see what is SPAKE2 protocol. This paper
by &lt;a class="reference external" href="https://www.di.ens.fr/~pointche/Documents/Papers/2005_rsa.pdf"&gt;Abdalla and Pointcheval&lt;/a&gt; gives full
explanation of SPAKE2 and proof of its security. I highly recommend reading the
paper as I can only summarize my understadning here.&lt;/p&gt;
&lt;p&gt;SPAKE2 is a variation of Diffie-Hellman problem we described above. Domain
parameters for SPAKE2 are &lt;span class="math"&gt;\((G, g, p, M, N, H)\)&lt;/span&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;cite&gt;G&lt;/cite&gt; is the group&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;g&lt;/cite&gt; is the generator for group&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;p&lt;/cite&gt; is the big prime which is order of group&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(M, N \in G\)&lt;/span&gt; and are selected by Alice and Bob respectively&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;H&lt;/cite&gt; is the hash function used to derive final shared key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Along with this SPAKE2 both side will have common password &lt;span class="math"&gt;\(pw \in Z_p\)&lt;/span&gt;.
Protocol is defined as follows&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Alice selects a random scalar &lt;span class="math"&gt;\(x \xleftarrow{R} Z_p\)&lt;/span&gt; and
calculates &lt;span class="math"&gt;\(X \leftarrow g^x\)&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Alice then computes &lt;span class="math"&gt;\(X^* \leftarrow X \cdot M^{pw}\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Bob selects a random scalar &lt;span class="math"&gt;\(y \xleftarrow{R} Z_p\)&lt;/span&gt; and calculates
&lt;span class="math"&gt;\(Y \leftarrow g^y\)&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Bob then computes &lt;span class="math"&gt;\(Y^* \leftarrow Y \cdot N^{pw}\)&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(X^*, Y^*\)&lt;/span&gt; are called pake messages and are sent to other side. i.e.
Alice sends &lt;span class="math"&gt;\(X^*\)&lt;/span&gt; to Bob and Bob sends &lt;span class="math"&gt;\(Y^*\)&lt;/span&gt; to Alice.&lt;/li&gt;
&lt;li&gt;Alice computes &lt;span class="math"&gt;\(K_A \leftarrow (Y*/N^{pw})^x\)&lt;/span&gt; and Bob computes &lt;span class="math"&gt;\(K_B
\leftarrow (X^*/M^{pw})^y\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Shared Key is calculated by Alice as &lt;span class="math"&gt;\(SK_A \leftarrow
H(A,B,X^*,Y^*,pw,K_A)\)&lt;/span&gt; and Bob computes &lt;span class="math"&gt;\(SK_B \leftarrow H(A,B,X^*,Y^*,
pw, K_B)\)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span class="math"&gt;\(SK_A = SK_B\)&lt;/span&gt; because mathematically value &lt;span class="math"&gt;\(K_A = K_B\)&lt;/span&gt; (you can
expand &lt;span class="math"&gt;\(X^*\)&lt;/span&gt; and &lt;span class="math"&gt;\(Y^*\)&lt;/span&gt; in step &lt;cite&gt;6&lt;/cite&gt; aboveand see that they are really
same).&lt;/p&gt;
&lt;p&gt;In step &lt;cite&gt;7&lt;/cite&gt; we calculate Hash of transcript, where &lt;cite&gt;A&lt;/cite&gt; and &lt;cite&gt;B&lt;/cite&gt; are identities of
Alice and Bob. and rest is calculated during protocol execution.&lt;/p&gt;
&lt;p&gt;One thing to note here is paper does not define what are identities or which
hash function is used. This allows some creativity from implementer side to
choose things. For &lt;em&gt;python-spake2&lt;/em&gt; interoperability &lt;em&gt;Brian&lt;/em&gt; has written a
&lt;a class="reference external" href="http://www.lothar.com/blog/57-SPAKE2-Interoperability/"&gt;detailed blog post&lt;/a&gt;
describing decision he has taken for all these points which are not defined in
original paper.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="curve-ed25519-group"&gt;
&lt;h2&gt;Curve Ed25519 Group&lt;/h2&gt;
&lt;p&gt;Now that we have seen the SPAKE2 protocol, we will next see the use of Elliptic
Curve groups in it and see how it varies.&lt;/p&gt;
&lt;p&gt;SPAKE2 uses &lt;em&gt;Abelian Group&lt;/em&gt; with large number of &amp;quot;elements&amp;quot;. We know that
Elliptic curve groups are Abelian groups, so we can fit them in SPAKE2. &lt;a class="reference external" href="http://lothar.com/blog/"&gt;Brian
Warner&lt;/a&gt; has choosen elliptic curve group &lt;em&gt;Ed25519&lt;/em&gt;
(some times also referred as X25519) as default group in &lt;em&gt;python-spake2&lt;/em&gt;
implementation. This is the same group which is used in &lt;em&gt;Ed25519 signature
scheme&lt;/em&gt;. The difference between multiplicative integer group modulo p and
elliptic curve group is that, element in integer group is just a number but in
elliptic curve group its a point. (represented by 2 co-ordinates).&lt;/p&gt;
&lt;p&gt;Curve Ed25519 which is actually called Edwards25519 is a &lt;em&gt;twisted Edwards
curve&lt;/em&gt;, defined in affine form as &lt;span class="math"&gt;\(ax^2 + y^2 = 1 + dx^2y^2\)&lt;/span&gt; where
&lt;span class="math"&gt;\(d \in k\{0,1\}\)&lt;/span&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;span class="math"&gt;\(q = 2^{255} - 19\)&lt;/span&gt; is the order of curve groups&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(l = 2^{252} + 27742317777372353535851937790883648493\)&lt;/span&gt; is the order of
curve subgroup.&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(a = -1\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(d = \frac{-121665}{121666}\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Base point &lt;span class="math"&gt;\(B\)&lt;/span&gt; is unique and has y-co-ordinate &lt;cite&gt;:math:4/5&lt;/cite&gt; and x
co-ordinate is positive.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Curve itself is given as &lt;span class="math"&gt;\(E/\mathbb F_q\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
-x^2 + y^2 = 1 - \frac{121665}{121666} x^2y^2
\end{equation*}
&lt;/div&gt;
&lt;p&gt;This curve is birationally equivalaent to the Montgomery curve known as
&lt;em&gt;Curve25519&lt;/em&gt;. If you are wondering what &lt;em&gt;25519&lt;/em&gt; is?, well its in the order of
group i.e. &lt;span class="math"&gt;\(2^{255} - 19\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Till now we were working with elliptic curves with affine co-ordinates, i.e.
each point is represented as &lt;span class="math"&gt;\((x,y)\)&lt;/span&gt;. But for fast operation twisted
edwards curve introduces new type of co-ordinates called &lt;em&gt;Extended Co-ordinates&lt;/em&gt;
where &lt;em&gt;x, y&lt;/em&gt; is represented as &lt;em&gt;X,Y,T and Z&lt;/em&gt;, and affine co-ordinates are
represented using the extended co-ordinates as follows&lt;/p&gt;
&lt;div class="math"&gt;
\begin{align*}
x = X/Z \\
y = Y/Z \\
x*y = T/Z \\
\end{align*}
&lt;/div&gt;
&lt;p&gt;Initial base point is converted to extended co-ordinate using &lt;cite&gt;Z&lt;/cite&gt; as 1. In all
above case the operations are &lt;span class="math"&gt;\(mod q\)&lt;/span&gt;. Additionally all division
operations are actually multiplication with inverse of element.&lt;/p&gt;
&lt;p&gt;We also noted above, Base point represented using only y co-ordinate. This is
because x co-ordinate can be recovered from y, using twisted edwards curve
equation we defined above. In most of libraries you will see that this
compressed notation of representing a point as just &lt;cite&gt;y&lt;/cite&gt; co-ordinate is used.
(Its called &lt;em&gt;CompressedEdwardsY&lt;/em&gt; in Rust's &lt;em&gt;curve25519-dalek&lt;/em&gt; crate.)&lt;/p&gt;
&lt;p&gt;In all above case the operations are &lt;span class="math"&gt;\(mod q\)&lt;/span&gt;. Additionally all division
operations are actually multiplication with inverse of element.Inverse of a
element is calculated as point raised to power &lt;cite&gt;q-2&lt;/cite&gt; modulo &lt;cite&gt;q&lt;/cite&gt;. I could not
find the technical/mathematical reason behind this. If some one knows please let
me know. So the inverse operation can be mathematically defined as follows.&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
x^{-1} = x^{q - 2} \bmod{q}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;The addition and doubling operations are as per algorithms defined in
&lt;a class="reference external" href="http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html"&gt;hyperelliptic.org post&lt;/a&gt;. We have
seen scalar multiplication in &lt;a class="reference external" href="https://copyninja.info/blog/golang_spake2_2.html"&gt;second post of this series&lt;/a&gt;, which depends on addition
and doubling operation.&lt;/p&gt;
&lt;div class="section" id="spake2-using-ed25519-group"&gt;
&lt;h3&gt;SPAKE2 using Ed25519 group&lt;/h3&gt;
&lt;p&gt;Unlike normal elliptic curve here the domain parameters are slightly different.
Ed25519 domain parameters are defined as &lt;span class="math"&gt;\((q, d, B, l)\)&lt;/span&gt; where &lt;cite&gt;q&lt;/cite&gt; gives
the order of elliptic curve group and &lt;cite&gt;l&lt;/cite&gt; is the order of subgroup. &lt;cite&gt;B&lt;/cite&gt; is the
base point of the group.&lt;/p&gt;
&lt;p&gt;Now lets rewrite original SPAKE2 protocol using elliptic curve groups&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Alice selects a random scalar &lt;span class="math"&gt;\(x \xleftarrow{R} E/\mathbb F_q\)&lt;/span&gt; and calculates
&lt;span class="math"&gt;\(X \leftarrow B \cdot x\)&lt;/span&gt; and computes &lt;span class="math"&gt;\(X^* \leftarrow X + M \cdot
pw\)&lt;/span&gt;. Alice sends &lt;span class="math"&gt;\(X^*\)&lt;/span&gt; to Bob.&lt;/li&gt;
&lt;li&gt;Bob selects random scalar &lt;span class="math"&gt;\(y \xleftarrow{R} E/\mathbb F_q\)&lt;/span&gt; and
calculates &lt;span class="math"&gt;\(Y \leftarrow B \cdot y\)&lt;/span&gt; and computes &lt;span class="math"&gt;\(Y^* \leftarrow
Y + N \cdot pw\)&lt;/span&gt;. Bob sends &lt;span class="math"&gt;\(Y^*\)&lt;/span&gt; to Alice.&lt;/li&gt;
&lt;li&gt;Alice now calculates &lt;span class="math"&gt;\(K_A \leftarrow (Y^* - N \cdot pw) \cdot x\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Bob now calculates &lt;span class="math"&gt;\(K_B \leftarrow (X^* - M \cdot pw) \cdot y\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Shared key is calculated by Alice &lt;span class="math"&gt;\(SK_A \leftarrow H(A, B, X^*, Y^*,
pw, K_A)\)&lt;/span&gt; and by Bob &lt;span class="math"&gt;\(SK_B \leftarrow H(A,B, X^*, Y^*, pw, K_B)\)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In 3 and 4 if you expand &lt;span class="math"&gt;\(X^*\)&lt;/span&gt; and &lt;span class="math"&gt;\(Y^*\)&lt;/span&gt; you will see that
&lt;span class="math"&gt;\(K_A = K_B\)&lt;/span&gt;. And given password used by both sides are same we will arrive
at same shared key.&lt;/p&gt;
&lt;p&gt;As you see above protocol for SPAKE2 remains same only things what changed from
earlier is operations, exponentiation is changed to multiplication and division
to substraction. Since we do not explicitly define substraction what we do is
negate the password and do addition instead.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So we now have seen all the basics needed to start writing the actual Go code to
implement SPAKE2 library. It was bit long I know but if you know the basics
writing code is a cake walk!. (quoting from Ramakrishnan). So in the next post I
will start writing implementation notes.&lt;/p&gt;
&lt;/div&gt;
&lt;script type='text/javascript'&gt;if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
    var align = "center",
        indent = "0em",
        linebreak = "false";

    if (false) {
        align = (screen.width &lt; 768) ? "left" : align;
        indent = (screen.width &lt; 768) ? "0em" : indent;
        linebreak = (screen.width &lt; 768) ? 'true' : linebreak;
    }

    var mathjaxscript = document.createElement('script');
    mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
    mathjaxscript.type = 'text/javascript';
    mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';

    var configscript = document.createElement('script');
    configscript.type = 'text/x-mathjax-config';
    configscript[(window.opera ? "innerHTML" : "text")] =
        "MathJax.Hub.Config({" +
        "    config: ['MMLorHTML.js']," +
        "    TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
        "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
        "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
        "    displayAlign: '"+ align +"'," +
        "    displayIndent: '"+ indent +"'," +
        "    showMathMenu: true," +
        "    messageStyle: 'normal'," +
        "    tex2jax: { " +
        "        inlineMath: [ ['\\\\(','\\\\)'] ], " +
        "        displayMath: [ ['$$','$$'] ]," +
        "        processEscapes: true," +
        "        preview: 'TeX'," +
        "    }, " +
        "    'HTML-CSS': { " +
        "        availableFonts: ['STIX', 'TeX']," +
        "        preferredFont: 'STIX'," +
        "        styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
        "        linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
        "    }, " +
        "}); " +
        "if ('default' !== 'default') {" +
            "MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
            "MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
        "}";

    (document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
    (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
&lt;/script&gt;</content><category term="development"/><category term="go"/><category term="golang"/><category term="spake2"/><category term="cryptography"/><category term="ecc"/></entry><entry><title>SPAKE2 In Golang: Finite fields of Elliptic Curve</title><link href="https://copyninja.in/blog/golang_spake2_3.html" rel="alternate"/><published>2018-08-12T22:51:00+05:30</published><updated>2018-08-12T22:51:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-08-12:/blog/golang_spake2_3.html</id><summary type="html">&lt;p class="first last"&gt;Third post in SPAKE2 in Golang. This post is my notes on finite fields
in elliptic curve group.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my &lt;a class="reference external" href="https://copyninja.info/blog/golang_spake2_2.html"&gt;previous post&lt;/a&gt; I
talked about elliptic curve basics and how the operations are done on elliptic
curves, including the algebraic representation which is needed for computers.
For usage in cryptography we need a elliptic curve group with some specified
number of elements, that is what we called &lt;strong&gt;Finite Fields&lt;/strong&gt;. We limit Elliptic
Curve groups with some big prime number &lt;cite&gt;p&lt;/cite&gt;. In this post I will try to briefly
explain &lt;em&gt;finite fields over elliptic curve&lt;/em&gt;.&lt;/p&gt;
&lt;div class="section" id="finite-fields"&gt;
&lt;h2&gt;Finite Fields&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Finite field&lt;/em&gt; or also called &lt;em&gt;Galois Field&lt;/em&gt; is a set with finite number of
elements. An example we can give is &lt;em&gt;integer modulo `p`&lt;/em&gt; where &lt;cite&gt;p&lt;/cite&gt; is prime.
Finite fields can be denoted as &lt;span class="math"&gt;\(\mathbb Z/p, GF(p)\)&lt;/span&gt; or &lt;span class="math"&gt;\(\mathbb
F_p\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Finite fields will have 2 operations addition and multiplications. These
operations are closed, associative and commutative. There exists a unique
identity element and inverse element for every element in the set.&lt;/p&gt;
&lt;p&gt;Division operation in finite fields is defined as &lt;span class="math"&gt;\(x / y = x \cdot y^{-1}\)&lt;/span&gt;,
that is x multiplied by inverse of y. and substraction &lt;span class="math"&gt;\(x - y\)&lt;/span&gt; is defined
in terms of addition as &lt;span class="math"&gt;\(x + (-y)\)&lt;/span&gt; which is x added by negation of y.
Multiplicative inverse can be &lt;em&gt;easily&lt;/em&gt; calculated using &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm"&gt;extended Euclidean
algorithm&lt;/a&gt;  which
I've not understood yet myself as there were readily available library functions
which does this for us. But I hear from Ramakrishnan that its very easy one.&lt;/p&gt;
&lt;div class="section" id="elliptic-curve-in-mathbb-f-p"&gt;
&lt;h3&gt;Elliptic Curve in &lt;span class="math"&gt;\(\mathbb F_p\)&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Now we understood what is finite fields we now need to restrict our elliptic
curves to the finite field. So our original definition of elliptic curve becomes
slightly different, that is we will have &lt;cite&gt;modulo p&lt;/cite&gt; to restrict the elements.&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
\begin{array}{rcl}
\left\{(x, y) \in (\mathbb{F}_p)^2 \right. &amp;amp; \left. | \right. &amp;amp; \left. y^2 \equiv x^3 + ax + b \pmod{p}, \right. \\
&amp;amp; &amp;amp; \left. 4a^3 + 27b^2 \not\equiv 0 \pmod{p}\right\}\ \cup\ \left\{0\right\}
\end{array}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;All our previous operations can now be written as follows&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
\begin{array}{rcl}
x_R &amp;amp; = &amp;amp; (m^2 - x_P - x_Q) \bmod{p} \\
y_R &amp;amp; = &amp;amp; [y_P + m(x_R - x_P)] \bmod{p} \\
&amp;amp; = &amp;amp; [y_Q + m(x_R - x_Q)] \bmod{p}
\end{array}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;Where slope, when &lt;span class="math"&gt;\(P \neq Q\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
m = (y_P - y_Q)(x_P - x_Q)^{-1} \bmod{p}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;and when &lt;span class="math"&gt;\(P = Q\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
m = (3 x_P^2 + a)(2 y_P)^{-1} \bmod{p}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;So now we need to know &lt;em&gt;order&lt;/em&gt; of this finite field. &lt;em&gt;Order&lt;/em&gt; of elliptic curve
finite field can be defined as &lt;strong&gt;number of points in the finite field&lt;/strong&gt;. Unlike
&lt;em&gt;integer modulo p&lt;/em&gt; where number of elements are &lt;em&gt;0 to p-1&lt;/em&gt;, in case of elliptic
curve you need to count points from &lt;cite&gt;x&lt;/cite&gt; to &lt;cite&gt;p-1&lt;/cite&gt;. This counting will be
&lt;span class="math"&gt;\(O(p)\)&lt;/span&gt;. Given large &lt;cite&gt;p&lt;/cite&gt; this will be &lt;em&gt;hard&lt;/em&gt; problem. But there are faster
algorithm to count order of group, which even I don't know much in detail :).
But from my reference its called &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Schoof%27s_algorithm"&gt;Schoof's algorithm&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="scalar-multiplication-and-cyclic-group"&gt;
&lt;h3&gt;Scalar Multiplication and Cyclic Group&lt;/h3&gt;
&lt;p&gt;When we consider scalar multiplication over elliptic curve finite fields, we
discover a special property. Taking example from &lt;a class="reference external" href="http://andrea.corbellini.name/2015/05/23/elliptic-curve-cryptography-finite-fields-and-discrete-logarithms/"&gt;Andrea Corbellini's post&lt;/a&gt;,
consider curve &lt;span class="math"&gt;\(y^2 \equiv x^3 + 2x + 3 ( mod 97)\)&lt;/span&gt; and point &lt;span class="math"&gt;\(P =
(3,6)\)&lt;/span&gt;. If we try calculating multiples of &lt;cite&gt;P&lt;/cite&gt;&lt;/p&gt;
&lt;div class="math"&gt;
\begin{align*}
0P = 0 \\
1P = (3,6) \\
2P = (80,10) \\
3P = (80,87) \\
4P = (3, 91) \\
5P = 0 \\
6P = (3,6) \\
7P = (80, 10) \\
8P = (80, 87) \\
9P = (3, 91) \\
...
\end{align*}
&lt;/div&gt;
&lt;p&gt;If you are wondering how to calculate above (I did at first). You need to use
point addition formula from earlier post where &lt;cite&gt;P = Q&lt;/cite&gt; with &lt;cite&gt;mod 97&lt;/cite&gt;. So we
observe that there are only 5 multiples of P and they are repeating cyclicly. we
can write above points as&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;span class="math"&gt;\(5kP = 0P\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\((5k + 1)P = 1P\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\((5k + 2)P = 2P\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\((5k + 3)P = 3P\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\((5k + 4)P = 4P\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or simply we can write these as &lt;span class="math"&gt;\(kP = (k mod 5)P\)&lt;/span&gt;. We also note that all
these 5 Points are closed under addition. This means &lt;strong&gt;adding two multiples of P,
we obtain a multiple of P and the set of multiples of P form cyclic subgroup&lt;/strong&gt;&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
nP + mP = \underbrace{P + \cdots + P}_{n\ \text{times}} + \underbrace{P +
\cdots + P}_{m\ \text{times}} = (n + m)P
\end{equation*}
&lt;/div&gt;
&lt;p&gt;Cyclic subgroups are foundation of Elliptic Curve Cryptography (ECC).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="subgroup-order"&gt;
&lt;h3&gt;Subgroup Order&lt;/h3&gt;
&lt;p&gt;Subgroup order tells how many points are really there in the subgroup. We can
redefine the &lt;em&gt;order of group&lt;/em&gt; in subgroup context as &lt;strong&gt;order of P is the
smallest positive integer such that nP = 0&lt;/strong&gt;. In above case if you see we have
smallest &lt;cite&gt;n&lt;/cite&gt; as &lt;cite&gt;5&lt;/cite&gt; since &lt;cite&gt;5P = 0&lt;/cite&gt;. So order of subgroup above is 5, it contains
5 element.&lt;/p&gt;
&lt;p&gt;Order of subgroup is linked to order of elliptic curve by &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Lagrange%27s_theorem_(group_theory)"&gt;Lagrange's Theorem&lt;/a&gt; which says
&lt;strong&gt;the order of subgroup is divisor of order of parent group&lt;/strong&gt;. Lagrange is
another name which I had read in my college, but the algorithms were different.&lt;/p&gt;
&lt;p&gt;From this we have following steps to find out the order of subgroup with base
point &lt;cite&gt;P&lt;/cite&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Calculate the elliptic curve's order &lt;cite&gt;N&lt;/cite&gt; using Schoof's algorithm.&lt;/li&gt;
&lt;li&gt;Find out all divisors of &lt;cite&gt;N&lt;/cite&gt;.&lt;/li&gt;
&lt;li&gt;For every divisor of &lt;cite&gt;n&lt;/cite&gt;, compute &lt;cite&gt;nP&lt;/cite&gt;.&lt;/li&gt;
&lt;li&gt;The smallest &lt;cite&gt;n&lt;/cite&gt; such that &lt;cite&gt;nP = 0&lt;/cite&gt; is the order of subgroup &lt;cite&gt;N&lt;/cite&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that its important to choose smallest divisor, not a random one. In above
examples 5P, 10P, 15P all satisfy condition but order of subgroup is 5.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="finding-base-point"&gt;
&lt;h3&gt;Finding Base Point&lt;/h3&gt;
&lt;p&gt;Far all above which is used in ECC, i.e. Group, subgroup and order we need a
base point &lt;cite&gt;P&lt;/cite&gt; to work with. So base point calculation is not done at the
beginning but in the end i.e. first choose a order which looks good then look
for subgroup order and finally find the suitable base point.&lt;/p&gt;
&lt;p&gt;We learnt above that subgroup order is divisor of group order which is derived
from &lt;em&gt;Lagrange's Theorem&lt;/em&gt;.  This term &lt;span class="math"&gt;\(h = N/n\)&lt;/span&gt; is actually called
&lt;strong&gt;co-factor of the subgroup&lt;/strong&gt;. Now why is this term co-factor important?.
Without going into details, this co-factor is used to find generator for the
subgroup as &lt;span class="math"&gt;\(G = hP\)&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So now are you wondering why I went on such length to describe all these?. Well
one thing I wanted to make some notes for myself because you can't find all
these information in single place, another these topics we talked in my previous
post and this point forms the domain parameters of &lt;em&gt;Elliptic Curve
Cryptography&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Domain parameters in ECC are the parameters which are known publicly to every
one. Following are 6 parameters&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Prime &lt;cite&gt;p&lt;/cite&gt; which is order of Finite field&lt;/li&gt;
&lt;li&gt;Co-efficients of curve &lt;cite&gt;a&lt;/cite&gt; and &lt;cite&gt;b&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Base point &lt;span class="math"&gt;\(\mathbb G\)&lt;/span&gt; the generator which is the base point of curve
that generates subgroup&lt;/li&gt;
&lt;li&gt;Order of subgroup &lt;cite&gt;n&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Co-factor &lt;cite&gt;h&lt;/cite&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So in short following is the domain parameters of ECC &lt;span class="math"&gt;\((p, a, b, G, n, h)\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In my next post I will try to talk about the specific curve group which is used
in SPAKE2 implementation called &lt;strong&gt;twisted Edwards curve&lt;/strong&gt; and give a brief
overview of SPAKE2 protocol.&lt;/p&gt;
&lt;/div&gt;
&lt;script type='text/javascript'&gt;if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
    var align = "center",
        indent = "0em",
        linebreak = "false";

    if (false) {
        align = (screen.width &lt; 768) ? "left" : align;
        indent = (screen.width &lt; 768) ? "0em" : indent;
        linebreak = (screen.width &lt; 768) ? 'true' : linebreak;
    }

    var mathjaxscript = document.createElement('script');
    mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
    mathjaxscript.type = 'text/javascript';
    mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';

    var configscript = document.createElement('script');
    configscript.type = 'text/x-mathjax-config';
    configscript[(window.opera ? "innerHTML" : "text")] =
        "MathJax.Hub.Config({" +
        "    config: ['MMLorHTML.js']," +
        "    TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
        "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
        "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
        "    displayAlign: '"+ align +"'," +
        "    displayIndent: '"+ indent +"'," +
        "    showMathMenu: true," +
        "    messageStyle: 'normal'," +
        "    tex2jax: { " +
        "        inlineMath: [ ['\\\\(','\\\\)'] ], " +
        "        displayMath: [ ['$$','$$'] ]," +
        "        processEscapes: true," +
        "        preview: 'TeX'," +
        "    }, " +
        "    'HTML-CSS': { " +
        "        availableFonts: ['STIX', 'TeX']," +
        "        preferredFont: 'STIX'," +
        "        styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
        "        linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
        "    }, " +
        "}); " +
        "if ('default' !== 'default') {" +
            "MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
            "MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
        "}";

    (document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
    (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
&lt;/script&gt;</content><category term="development"/><category term="go"/><category term="golang"/><category term="spake2"/><category term="cryptography"/><category term="ecc"/></entry><entry><title>SPAKE2 In Golang: Elliptic Curves Primer</title><link href="https://copyninja.in/blog/golang_spake2_2.html" rel="alternate"/><published>2018-07-28T13:22:00+05:30</published><updated>2018-07-28T13:22:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-07-28:/blog/golang_spake2_2.html</id><summary type="html">&lt;p class="first last"&gt;Second post in series SPAKE2 in Golang, my notes on Elliptic curves
and groups&lt;/p&gt;
</summary><content type="html">&lt;!--  --&gt;
&lt;blockquote&gt;
TLDR; this post is going to be too long and mostly theoretical. If you are
wondering about where is Go in all these posts, please wait for few more
posts before I can write about the actual implementation.&lt;/blockquote&gt;
&lt;p&gt;In my &lt;a class="reference external" href="https://copyninja.info/blog/golang_spake2_1.html"&gt;previous post&lt;/a&gt; I
talked about starting of my new adventure to write a cryptographic library and
how I tried to brute force to solve problem without knowing basics. In this post
I'll talk about my learning of &lt;em&gt;Elliptic Curves and their Groups&lt;/em&gt;. This post is
just my notes and I'm not trying to explain all basics or mathematics behind the
Elliptic curves.&lt;/p&gt;
&lt;p&gt;Ramakrishnan gave me a good article to start with Elliptic curves. Its a series of
posts by &lt;em&gt;Andrea Corbellini&lt;/em&gt;, which starts with &lt;a class="reference external" href="http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/"&gt;Elliptic Curve Cryptography: A
Gentle Introduction&lt;/a&gt;.
These posts gave me a great deal of understanding about elliptic curves and how
elliptic curve cryptography works, and why its faster. If you want to learn
about elliptic curve I highly recommend you to go through the series.&lt;/p&gt;
&lt;div class="section" id="elliptic-curves"&gt;
&lt;h2&gt;Elliptic Curves&lt;/h2&gt;
&lt;p&gt;Elliptic curves are set of points described by equation&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
y^2 = x^3 + ax + b
\end{equation*}
&lt;/div&gt;
&lt;p&gt;where &lt;cite&gt;a&lt;/cite&gt; and &lt;cite&gt;b&lt;/cite&gt; are the coefficients which needs to satisfy &lt;span class="math"&gt;\(4a^3 + 27b^2
\neq 0\)&lt;/span&gt;. This form of equation is called &lt;em&gt;Weirstrass normal form of elliptic
curves&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Along with normal point there is also point on curve which is considered ideal
point and is &lt;em&gt;point at infinity&lt;/em&gt;; it is denoted by symbol 0. So considering
point at infinity we can define elliptic curve as&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
\{(x,y) \in \mathbb R ^2 | y^2 = x^3 + ax + b, 4a^3 + 27b^2 \neq 0 \} \cup  \{0\}
\end{equation*}
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="groups"&gt;
&lt;h2&gt;Groups&lt;/h2&gt;
&lt;p&gt;Before going to Elliptic curve groups we need to know what are groups. I now
remembered my academics where I had studied about groups and number theory in
general. That time never knew where exactly it was useful. And I should really
say learning something without knowing its application is really difficult.
Moving on to the groups,&lt;/p&gt;
&lt;p&gt;A group in mathematics is basically a set for which there is a binary operation
which is called as &lt;em&gt;&amp;quot;addition&amp;quot;&lt;/em&gt; and idicated with + symbol. In order for set
&lt;span class="math"&gt;\(\mathbb G\)&lt;/span&gt; the binary operation must be defined so that it has following
properties.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;strong&gt;closure&lt;/strong&gt;: if &lt;cite&gt;a&lt;/cite&gt; and &lt;cite&gt;b&lt;/cite&gt; are members of of &lt;span class="math"&gt;\(\mathbb G\)&lt;/span&gt; then
&lt;span class="math"&gt;\(a + b\)&lt;/span&gt; is also member of &lt;span class="math"&gt;\(\mathbb G\)&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;associativity&lt;/strong&gt;: &lt;span class="math"&gt;\((a + b) + c = a + (b + c);\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;there exists an &lt;strong&gt;identity element&lt;/strong&gt; 0 such that &lt;span class="math"&gt;\(a + 0 = 0 + a = a;\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Every element has a inverse, that is for every &lt;cite&gt;a&lt;/cite&gt; there exists &lt;cite&gt;b&lt;/cite&gt; such that
&lt;span class="math"&gt;\(a + b = 0\)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For a group to be Abelian there is a 5th rule.&lt;/p&gt;
&lt;ol class="arabic simple" start="5"&gt;
&lt;li&gt;&lt;strong&gt;commutativity&lt;/strong&gt;: &lt;span class="math"&gt;\(a + b = b + a\)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If a group satisfies we get some additional property such that &lt;strong&gt;unique identity
element&lt;/strong&gt; and &lt;strong&gt;unique inverse element&lt;/strong&gt; which is either directly or indirectly
very important.&lt;/p&gt;
&lt;div class="section" id="elliptic-curve-groups"&gt;
&lt;h3&gt;Elliptic Curve Groups&lt;/h3&gt;
&lt;p&gt;Similar to number groups we defined above, its possible to have group over
elliptic curves. Following are the property or rule for a Elliptic curve groups.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Elements of the groups are point on elliptic curve;&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;identity element&lt;/strong&gt; is the point at infinity; yes the one we described
above while defining elliptic curves.&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;inverse&lt;/strong&gt; of a point &lt;span class="math"&gt;\(\mathrm R\)&lt;/span&gt; is the one symmetric on
&lt;cite&gt;x-axis&lt;/cite&gt;. i.e. if point is &lt;span class="math"&gt;\((x,y)\)&lt;/span&gt; then inverse of the point is
&lt;span class="math"&gt;\((x, -y)\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;adition&lt;/strong&gt; is given by the rules: &lt;strong&gt;given three aligned, non-zero points,&lt;/strong&gt;
&lt;span class="math"&gt;\(\mathrm P,Q\)&lt;/span&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;span class="math"&gt;\(\mathrm R\)&lt;/span&gt; &lt;strong&gt;their sum is&lt;/strong&gt;
&lt;span class="math"&gt;\(P + Q + R = 0\)&lt;/span&gt;.
This means the line through the 3 point passes through the point at infinity.&lt;/li&gt;
&lt;li&gt;For addition we want 3 points to be aligned and does not require any specific
order which means
&lt;span class="math"&gt;\(P + (Q + R) = Q + (P + R) = R + (P + Q) = ... = 0\)&lt;/span&gt; that is &lt;strong&gt;our +
operator is both associative and commutative&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By point 5 we conclude that Elliptic curve groups are &lt;em&gt;Abelian&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="algebraic-addition"&gt;
&lt;h3&gt;Algebraic Addition&lt;/h3&gt;
&lt;p&gt;Since we know &lt;span class="math"&gt;\(P + Q + R = 0\)&lt;/span&gt; we can say &lt;span class="math"&gt;\(P + Q = -R\)&lt;/span&gt;. This means we
draw a line on elliptic curve which passes through point &lt;cite&gt;P&lt;/cite&gt; and &lt;cite&gt;Q&lt;/cite&gt; it
intersects the curve at 3rd point &lt;cite&gt;R&lt;/cite&gt;. Inverse of point &lt;cite&gt;R&lt;/cite&gt; is &lt;cite&gt;-R&lt;/cite&gt; and is the
result of addition of 2 points &lt;cite&gt;P&lt;/cite&gt; and &lt;cite&gt;Q&lt;/cite&gt;.  This is easy geometrically but for
computers, we need to represent this with algebraic notation. This is where the
&lt;em&gt;slope of line&lt;/em&gt; comes to picture, another academic topic which I learnt without
actually knowing its real world application.&lt;/p&gt;
&lt;p&gt;So considering point &lt;cite&gt;P&lt;/cite&gt; as &lt;span class="math"&gt;\((x_P,y_P)\)&lt;/span&gt; and &lt;cite&gt;Q&lt;/cite&gt; as &lt;span class="math"&gt;\((x_Q, y_Q)\)&lt;/span&gt; we
can calculate slope of line going from &lt;cite&gt;P&lt;/cite&gt; to &lt;cite&gt;Q&lt;/cite&gt; as follows&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
m = \frac{y_P - y_Q}{x_P - x_Q}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;And in a special case where &lt;span class="math"&gt;\(P = Q\)&lt;/span&gt; formula is slightly different&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
m = \frac{3x_P^2 + a}{2y_P}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;Intersection of this line with curve is point &lt;cite&gt;R&lt;/cite&gt; &lt;span class="math"&gt;\((x_R,y_R)\)&lt;/span&gt; and point
&lt;span class="math"&gt;\(x_R\)&lt;/span&gt; and &lt;span class="math"&gt;\(y_R\)&lt;/span&gt; are calculated using following formula.&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
x_R = m^2 - x_P - x_Q
\end{equation*}
&lt;/div&gt;
&lt;div class="math"&gt;
\begin{equation*}
y_R =
\begin{cases}
y_P + m(x_R - x_P), &amp;amp; \text{or} \\
y_Q + m(x_R - x_Q)
\end{cases}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;I've not mentioned about special cases of elliptic curve additions which is
explained in &lt;a class="reference external" href="http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/"&gt;Andrea Corbellini&lt;/a&gt;
blog. Please refer for more mathematical oriented explanation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="scalar-multiplication"&gt;
&lt;h3&gt;Scalar Multiplication&lt;/h3&gt;
&lt;p&gt;One more important operation we do with elliptic curve group is scalar
multiplication. It allows you to calculate &lt;span class="math"&gt;\(nP\)&lt;/span&gt; where &lt;cite&gt;n&lt;/cite&gt; is a natural
number. Scalar multiplication can be implemented using addition as follows.&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
nP = \underbrace{P + P + \cdots + P}_{n\ \text{times}}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;This property is what makes elliptic curves attractive and faster than the
normal integer groups where scalar multiplication is actually exponentiation
operation.&lt;/p&gt;
&lt;p&gt;If we see scalar multiplication formula above, we see that it requires &lt;cite&gt;n&lt;/cite&gt;
addition, which can be &lt;span class="math"&gt;\(O(n)\)&lt;/span&gt; operation or, if we consider &lt;cite&gt;n&lt;/cite&gt; as &lt;cite&gt;k&lt;/cite&gt; bit
integer then algorithm will be &lt;span class="math"&gt;\(O(2^k)`which looks highly inefficient when
`n\)&lt;/span&gt; is large prime number.&lt;/p&gt;
&lt;p&gt;But there is another algorithm which is much faster for this purpose, its called
&lt;strong&gt;double and add&lt;/strong&gt; you can find &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication"&gt;wikipedia article on it&lt;/a&gt;. First I
did not understand this, but after a while of struggling, and trying to
implement it myself it became pretty clear. It works with first taking binary
representation of &lt;cite&gt;n&lt;/cite&gt; &lt;span class="math"&gt;\(n = n_0 + 2n_1 + 2^2_n2 + ...+2^kn_k\)&lt;/span&gt; where
&lt;span class="math"&gt;\([n_0..n_k] \in \{0,1\}\)&lt;/span&gt;. Below is pseudo code for the recursive version
of algorithm.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scalarmult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="c1"&gt;# identity element&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;           &lt;span class="c1"&gt;# n is odd we add point&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;point_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scalarmult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;scalarmult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point_double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# we double point and multiply by n/2&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Let's consider an example to understand what is this algorithm doing. Lets say
we want to caculate &lt;cite&gt;21P&lt;/cite&gt;. First thing is we denote &lt;cite&gt;21&lt;/cite&gt; as binary string
&lt;cite&gt;10101&lt;/cite&gt; now skipping all those 0's and consider only the 1's, so we will have
&lt;span class="math"&gt;\(2^4 + 2^2 + 2^0\)&lt;/span&gt;. Now if we multiply P to this representation. So this
algorithm calculates &lt;cite&gt;21P&lt;/cite&gt; as &lt;span class="math"&gt;\(16P + 4P + P\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;If we consider doubling and adding as constant operations i.e. &lt;span class="math"&gt;\(O(1)\)&lt;/span&gt; then
this algorithm will be &lt;span class="math"&gt;\(O(\log n)\)&lt;/span&gt; (in above 21 can be calculated in 3
operations which is &lt;span class="math"&gt;\(\log 21\)&lt;/span&gt;) which is much better than earlier
&lt;span class="math"&gt;\(O(n)\)&lt;/span&gt; algorithm.&lt;/p&gt;
&lt;p&gt;Given &lt;cite&gt;n&lt;/cite&gt; and &lt;cite&gt;P&lt;/cite&gt; we can easily cacluate &lt;span class="math"&gt;\(Q = nP\)&lt;/span&gt; but given &lt;cite&gt;Q&lt;/cite&gt; and &lt;cite&gt;P&lt;/cite&gt;
there is no &lt;em&gt;easy&lt;/em&gt; way to find &lt;cite&gt;n&lt;/cite&gt; especially when numbers are big. This is the
&lt;em&gt;&amp;quot;hard&amp;quot;&lt;/em&gt; problem or the &lt;em&gt;discrete logarithm problem&lt;/em&gt; which makes cryptography
work.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So I learned now about Elliptic curves, its group and operations like scalar
multiplication and addition. But this is not directly useful, we need to learn
about &lt;strong&gt;Finite Fields&lt;/strong&gt; and &lt;strong&gt;Elliptic Curve over Finite Field&lt;/strong&gt; and many more
concepts before we can go to actual implementation!. I thought of writing finite
field as part of this post, but then I've already written a lot and there is no
point in expanding this post more. So finite fields, cyclic groups will be part
of next post.&lt;/p&gt;
&lt;p&gt;As a closing note, if you are wondering why there is no mention of anything
about Go, you need to wait a bit more for my actual implementation notes in
Golang. I would like to write down entire learning process rather than directly
jumping to implementation. So please bare with me :-).&lt;/p&gt;
&lt;/div&gt;
&lt;script type='text/javascript'&gt;if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
    var align = "center",
        indent = "0em",
        linebreak = "false";

    if (false) {
        align = (screen.width &lt; 768) ? "left" : align;
        indent = (screen.width &lt; 768) ? "0em" : indent;
        linebreak = (screen.width &lt; 768) ? 'true' : linebreak;
    }

    var mathjaxscript = document.createElement('script');
    mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
    mathjaxscript.type = 'text/javascript';
    mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';

    var configscript = document.createElement('script');
    configscript.type = 'text/x-mathjax-config';
    configscript[(window.opera ? "innerHTML" : "text")] =
        "MathJax.Hub.Config({" +
        "    config: ['MMLorHTML.js']," +
        "    TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
        "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
        "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
        "    displayAlign: '"+ align +"'," +
        "    displayIndent: '"+ indent +"'," +
        "    showMathMenu: true," +
        "    messageStyle: 'normal'," +
        "    tex2jax: { " +
        "        inlineMath: [ ['\\\\(','\\\\)'] ], " +
        "        displayMath: [ ['$$','$$'] ]," +
        "        processEscapes: true," +
        "        preview: 'TeX'," +
        "    }, " +
        "    'HTML-CSS': { " +
        "        availableFonts: ['STIX', 'TeX']," +
        "        preferredFont: 'STIX'," +
        "        styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
        "        linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
        "    }, " +
        "}); " +
        "if ('default' !== 'default') {" +
            "MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
            "MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
        "}";

    (document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
    (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
&lt;/script&gt;</content><category term="development"/><category term="go"/><category term="golang"/><category term="spake2"/><category term="cryptography"/><category term="ecc"/></entry><entry><title>SPAKE2 In Golang: Journey to Cryptoland begins</title><link href="https://copyninja.in/blog/golang_spake2_1.html" rel="alternate"/><published>2018-07-22T22:07:00+05:30</published><updated>2018-07-22T22:07:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-07-22:/blog/golang_spake2_1.html</id><summary type="html">&lt;p class="first last"&gt;My notes on SPAKE2 implementation in Golang, my first Golang and
cryptographic library&lt;/p&gt;
</summary><content type="html">&lt;!--  --&gt;
&lt;blockquote&gt;
This or the series of SPAKE2 related posts are inspired from &lt;a class="reference external" href="https://jml.io"&gt;Jonathan
Lange's&lt;/a&gt; &lt;a class="reference external" href="https://jml.io/tag/spake2.html"&gt;series on SPAKE2&lt;/a&gt; when he ported it to Haskell, which is
also the reference I used for my implementation in Golang.&lt;/blockquote&gt;
&lt;div class="section" id="brief-background"&gt;
&lt;h2&gt;Brief Background&lt;/h2&gt;
&lt;p&gt;Before I can go to detail I should tell why/how I came to implementing SPAKE2 in
Golang. Story starts a couple of month back when I started contributing to
&lt;a class="reference external" href="https://github.com/warner/magic-wormhole.rs"&gt;*magic-wormhole.rs*&lt;/a&gt;, a Rust port
of original Python project of magic-wormhole. You can read &lt;a class="reference external" href="https://lwn.net/Articles/692061/"&gt;this LWN article&lt;/a&gt; to understand more about what
magic-wormhole is.&lt;/p&gt;
&lt;p&gt;During contribution my friend &lt;a class="reference external" href="https://rkrishnan.org/"&gt;Ramakrishnan Muthukrishnan&lt;/a&gt; said to me that I should try to port the
magic-wormhole to Golang. I was not a expert Go programmer but had understanding
of language basics and thought why not use it to improve my language
understanding. And this is where it all started.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-is-spake2-why-is-it-used"&gt;
&lt;h2&gt;What is SPAKE2 why is it used?&lt;/h2&gt;
&lt;p&gt;At this point we need to know why SPAKE2 is needed and how magic-wormhole uses
it. &lt;a class="reference external" href="http://www.di.ens.fr/~mabdalla/papers/AbPo05a-letter.pdf"&gt;SPAKE2&lt;/a&gt; is
&lt;em&gt;Simple Password Authenticated Key Exchange&lt;/em&gt; protocol. It allows 2 parties
having a shared weak password to derive a strong shared key which can then be
used by the parties to setup a encrypted+authenticated channel between them.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;magic-wormhole&lt;/em&gt; uses SPAKE2 to negotiate a shared session key between
communicating parties which is then used by magic-wormhole to derive different
keys needed for different &lt;em&gt;purpose&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So I hit my first road block after agreeing to implement the &lt;em&gt;magic-wormhole&lt;/em&gt; in
Golang, there is no SPAKE2 implementation readily available in Go!.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="enter-cryptography-and-my-knowledge-about-it"&gt;
&lt;h2&gt;Enter Cryptography and My knowledge about it&lt;/h2&gt;
&lt;p&gt;Ram convinced me that its easy to implement SPAKE2 in Go and I agreed. But my
knowledge on cryptography was limited. I knew Cryptography is&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;basically math with big numbers and relies on fact that factoring big prime
number is hard for computers.&lt;/li&gt;
&lt;li&gt;These big numbers are derived from &lt;em&gt;Abelian Group&lt;/em&gt; and related concepts from
number theory, which I have studied in academics but since I've never learnt a
practical use case for them, its eating dust some where inside my memory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've taken some theoretical course on Cryptography but never thought of
implementing one myself. With these weak foundation I set out for a new
adventure.&lt;/p&gt;
&lt;div class="section" id="python-spake2-implementation"&gt;
&lt;h3&gt;Python SPAKE2 Implementation&lt;/h3&gt;
&lt;p&gt;Since magic-wormhole is implemented in python, SPAKE2 implementation in Python
is considered as reference for other language implementation. SPAKE2 paper does
not specify much about where or how the requirement public constants are
defined, so implementer can take liberty at defining those. Python code uses 2
groups one is &lt;em&gt;Twisted Edwards Curve&lt;/em&gt; group &lt;em&gt;Ed25519&lt;/em&gt; and others are
multiplicative group over Integer of 1024, 2048 and 3072 bits.&lt;/p&gt;
&lt;p&gt;In Python code Warner himself has defined Ed25519 and other Integer group and
related operations. In Rust code though there is only Ed25519 group but its
created using &lt;em&gt;curve25519-dalek&lt;/em&gt; library. Haskell code also defines the group
operations  by itself instead of depending on any other libraries (possibly
Cryptonite). So as a first step I started for searching any library equivalent
to &lt;em&gt;curve25519-dalek&lt;/em&gt;  as I've no clue what is an Elliptic curve.(forget groups
I don't know basic itself).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="first-try-bruteforce"&gt;
&lt;h3&gt;First Try, Bruteforce&lt;/h3&gt;
&lt;p&gt;I've this bad habit of tackling problem with brute force; some times it works but
most time it just exhausts me, taking me nowhere. So with my normal habit I
started looking for Ed25519 curve operations library. (Without actually knowing
what operations are and how it works). I tried to read through
&lt;em&gt;curve25519-dalek&lt;/em&gt; but invain, nothing entered into my head. I found &lt;em&gt;ed25519&lt;/em&gt;
package for Go written by &lt;em&gt;Adam Langley&lt;/em&gt; but eventually it turned out to be
actually a signature package. I found an internal package defined in &lt;em&gt;ed25519&lt;/em&gt;
package called &lt;em&gt;edwards25519&lt;/em&gt;, which seem to have some operations defined but I
was unable to understand it nor figure out why its made internal. I later even
took a dig at embedding &lt;em&gt;edwards25519&lt;/em&gt; as part of my implementation of ed25519
group but finally had to drop it for my own version that story will be part of
another post in this series.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;During all these I was constantly in talk with Ram and first thing he told me
was to slow down a bit and go from scratch. And that's what was the learning
point for me. In short I can say the following.&lt;/p&gt;
&lt;!--  --&gt;
&lt;blockquote&gt;
Nothing can be done in single day, before you code understand the basic
concepts and then build it from there. As they say you can't build a stable
house on weak foundation.&lt;/blockquote&gt;
&lt;p&gt;In the next post in this series I will write about my learning on Elliptic
Curves and Elliptic curve groups, followed by experiment with number groups and
finally learning and decision I had to make in writing &lt;em&gt;gospake2&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
</content><category term="development"/><category term="go"/><category term="golang"/><category term="spake2"/><category term="cryptography"/><category term="ecc"/><category term="magic-wormhole"/></entry><entry><title>Docker Private Registry and Self Signed Certificates</title><link href="https://copyninja.in/blog/docker-registry-selfsigned-cert.html" rel="alternate"/><published>2018-04-14T19:47:00+05:30</published><updated>2018-04-14T19:47:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-04-14:/blog/docker-registry-selfsigned-cert.html</id><summary type="html">&lt;p class="first last"&gt;Post describes additional steps that needs to be taken
while generating a self signed certificates for docker private
registry.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I was recently experimenting with hosting a private registry on an internal LAN
network for publishing docker private images. I found out that &lt;em&gt;docker-pull&lt;/em&gt;
works only with TLS secured registry. There is possible to run insecure registry
by editing &lt;em&gt;daemon.json&lt;/em&gt; file but its better to use self-signed certificates
instead.&lt;/p&gt;
&lt;p&gt;Once I followed the step and started registry I tried to &lt;em&gt;docker-pull&lt;/em&gt; and it
started complaining about certificate not having any valid names. But this same
certificate worked fine with browsers too, of course you need to add exception
but no other errors were encountered.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.docker.com/registry/insecure/"&gt;Documentation&lt;/a&gt; for Docker does
not speaks any specific settings needs to be done prior to generating a
self-signed certificate so I was bit confused at beginning.A bit of searching
showed up following &lt;a class="reference external" href="https://github.com/docker/for-linux/issues/248"&gt;issue&lt;/a&gt;
filed against docker and then later re-assigned against &lt;a class="reference external" href="https://github.com/golang/go/issues/24293"&gt;*Golang*&lt;/a&gt; for its method of handling x509
certificate. It appears that with valid &lt;em&gt;Subject Alternative Name&lt;/em&gt; Go crypto
library ignores the &lt;em&gt;Common Name&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;From thread on &lt;a class="reference external" href="https://security.stackexchange.com/questions/74345/provide-subjectaltname-to-openssl-directly-on-command-line"&gt;Security Stack Exchange&lt;/a&gt;
I found the command to create a self-signed certificate to contain self-signed
certificate. Command in excepted answer does not work until you add
&lt;em&gt;--extensions&lt;/em&gt; option to it as mentioned in one of the comments. Full command is
as shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;req&lt;span class="w"&gt; &lt;/span&gt;-new&lt;span class="w"&gt; &lt;/span&gt;-sha256&lt;span class="w"&gt; &lt;/span&gt;-key&lt;span class="w"&gt; &lt;/span&gt;domain.key&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;-subj&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/C=US/ST=CA/O=Acme, Inc./CN=example.com&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;-reqexts&lt;span class="w"&gt; &lt;/span&gt;SAN&lt;span class="w"&gt; &lt;/span&gt;-extensions&lt;span class="w"&gt; &lt;/span&gt;SAN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;-config&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/etc/ssl/openssl.cnf&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-out&lt;span class="w"&gt; &lt;/span&gt;domain.crt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You would need to replace values in &lt;em&gt;-subj&lt;/em&gt; and under &lt;em&gt;[SAN]&lt;/em&gt; extension. Benefit
of this command is you need not modify the &lt;em&gt;/etc/ssl/openssl.conf&lt;/em&gt; file.&lt;/p&gt;
&lt;p&gt;If you do not have a domain name for the registry and using IP address instead
consider replacing &lt;em&gt;[SAN]&lt;/em&gt; section in above command to have &lt;em&gt;IP: &amp;lt;ip-address&amp;gt;&lt;/em&gt;
instead of &lt;em&gt;DNS&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Happy hacking.!&lt;/p&gt;
</content><category term="devops"/><category term="docker"/><category term="container"/><category term="openssl"/></entry><entry><title>Docker container as Development Environment</title><link href="https://copyninja.in/blog/docker-dev-environment.html" rel="alternate"/><published>2018-04-14T13:15:00+05:30</published><updated>2018-04-14T13:15:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-04-14:/blog/docker-dev-environment.html</id><summary type="html">&lt;p class="first last"&gt;Post describing how Docker can be used to create uniform development
environment in development teams.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;When you have a distributed team working on a project, you need to make sure
that every one uses similar development environment. This is critical if you are
working on embedded systems project. There are multiple possibility for this
scenario.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Use a common development server and provide every developer in your team an
account in it.&lt;/li&gt;
&lt;li&gt;Provide description to every one how to setup their development environment
and trust them they will do so.&lt;/li&gt;
&lt;li&gt;Use Docker to provide the developer with ready made environment and use
build server (CI) for creating final deployment binaries.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1st approach was most common approach used, but it has some drawbacks. Since its
a shared system you should make sure not every one is able to install or modify
system and hence have a single administrator so that no one accidentally breaks
the development environment. Other problems include forced to use older OS due
to specific requirements of compilers etc.&lt;/p&gt;
&lt;p&gt;2nd approach makes you put your trust on your developer to get the correct
development environment. Of course you need to trust your team, but every one is
a human being and humans can make mistake.&lt;/p&gt;
&lt;div class="section" id="enter-docker"&gt;
&lt;h2&gt;Enter Docker&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Dockerfile&lt;/em&gt; is best way to document/setup development environment. A developer
can read &lt;em&gt;Dockerfile&lt;/em&gt; and understand what is being done to setup the environment
and simply execute &lt;cite&gt;docker build&lt;/cite&gt; command to generate his/her development
environment, or better you build the image and publish it in either public
registry and if that is not possible put it in a private registry, and ask
developers to pull a image of development environment.&lt;/p&gt;
&lt;p&gt;Don't be scared by &lt;em&gt;private registry&lt;/em&gt;, setting one up is not a humongous task!
Its just couple of docker commands and there is a pretty good &lt;a class="reference external" href="https://docs.docker.com/registry/deploying/#run-a-local-registry"&gt;documentation&lt;/a&gt; available
to set one up.&lt;/p&gt;
&lt;p&gt;While setting up a development environment you need to make sure last
instruction in your &lt;cite&gt;Dockerfile&lt;/cite&gt; is executing the shell of your choice. This is
because when you start a container this last instruction is what actually is run
by docker, and in our case we need to provide developer with a shell all build
toolchain and libraries.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;...
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/bin/bash&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now developer just needs to get/build the image, start the container and use it
for their work!. To summarize below command is sufficient for developer to run a
fresh environment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;devenv&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# If they are building it&lt;/span&gt;

&lt;span class="c1"&gt;# If they are pulling it from say private registry&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;private-registry-ip/path/to/devenv

$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-itd&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;development&lt;span class="w"&gt; &lt;/span&gt;devenv
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;attach&lt;span class="w"&gt; &lt;/span&gt;development
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When container is started it will execute the shell and the next attach command
will attach your shell's input/output to container. Now it can be used just like
normal shell to build the application.&lt;/p&gt;
&lt;p&gt;Another good thing which can be done is sharing the workspace with container so
your container can just contain the toolchain and library that is needed and all
version control, code editing and likewise can be done in the host machine. One
thing that would be needed to make sure is your UID on host and UID of the user
inside the container is same. This can be easily done by creating a separate
user in the container with UID same as your UID on host system.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="advantages"&gt;
&lt;h2&gt;Advantages&lt;/h2&gt;
&lt;p&gt;Some advantages of using docker container include&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;They are easy to setup and saves a lot of time to the team as a whole
compared to traditional approaches.&lt;/li&gt;
&lt;li&gt;Easy to throwaway and start fresh: If a developer thinks he did something
wrong with container he can prune it and create a fresh one based on the
development environment image. So this gives a lot of freedom to developer to
experiment.&lt;/li&gt;
&lt;li&gt;Uniformity: You will be sure that all your team will be using same
evnironment.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So you might ask what about other container technologies like systemd-nspawn or
lxc etc. Of course they can also be used in the similar fashion, infact before
experimenting with Docker I was a vivid user of &lt;em&gt;systemd-nspawn&lt;/em&gt; container. You
might have also seen my previous &lt;a class="reference external" href="https://copyninja.info/tags/systemd-nspawn.html"&gt;blog posts&lt;/a&gt; on &lt;em&gt;systemd-nspawn&lt;/em&gt; too.
Only reason I switched to Docker is its easy to setup unlike systemd-nspawn
which needs so many tweaking and tuning of things besides it does not have a
Dockerfile like approach which makes things more time consuming. So for me
Docker won the war and I shifted to using Docker more.&lt;/p&gt;
&lt;p&gt;This entire post was based on my experiment and experience with Docker. If you
feel something can be done in a better way please feel free to write to me.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="docker"/><category term="container"/></entry><entry><title>Biboumi - A XMPP - IRC Gateway</title><link href="https://copyninja.in/blog/xmpp-irc-gateway.html" rel="alternate"/><published>2018-03-11T10:49:00+05:30</published><updated>2018-03-11T10:49:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2018-03-11:/blog/xmpp-irc-gateway.html</id><summary type="html">&lt;p class="first last"&gt;A brief post explaining biboumi and its usage.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;IRC is a communication mode (technically a communication protocol) used by many
Free Software projects for communication and collaboration. It is serving these
projects well even 30 years after its inception. Though I'm pretty much okay
with IRC I had a problem of not able to use IRC from the mobile phones. Main
problem is the inconsistent network connection, where IRC needs always to be
connected. This is where I came across &lt;em&gt;Biboumi&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Biboumi&lt;/em&gt; by itself does not have anything to do with mobile phones, its just a
gateway which will allow you to connect with IRC channel as if it is a XMPP MUC
room from any XMPP client. Benefit of this is it allows to enjoy some of XMPP
feature in your IRC channel (not all but those which can be mapped).&lt;/p&gt;
&lt;p&gt;I run &lt;em&gt;Biboumi&lt;/em&gt; with my &lt;em&gt;ejabbered&lt;/em&gt; instance and there by now I can connect to
some of the &lt;em&gt;Debian&lt;/em&gt; IRC channel directly from my phone using &lt;em&gt;Conversations&lt;/em&gt;
XMPP client for Android.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Biboumi&lt;/em&gt; is packaged for Debian, though I'm co-maintainer of the package most
hardwork is done by &lt;em&gt;Jonas Smedegaard&lt;/em&gt; in keeping the package in shape. It is
also available for &lt;em&gt;stretch-backports&lt;/em&gt; (though slightly outdated as its not
packaged by us for backports). Once you install the package, copy example
configuration file from &lt;cite&gt;/usr/share/doc/biboumi/examples/example.conf&lt;/cite&gt; to
&lt;cite&gt;/etc/biboumi/biboumi.cfg&lt;/cite&gt; and modify the values as needed. Below is my sample
file with password redacted.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;biboumi.localhost&lt;/span&gt;
&lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;xxx&lt;/span&gt;
&lt;span class="na"&gt;db_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/lib/biboumi/biboumi.sqlite&lt;/span&gt;
&lt;span class="c1"&gt;#log_file=/var/log/biboumi/biboumi.log&lt;/span&gt;
&lt;span class="na"&gt;log_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;vasudev@copyninja.info&lt;/span&gt;
&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8888&lt;/span&gt;
&lt;span class="na"&gt;realname_customization&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;realname_from_jid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Explanation for all the key, values in the configuration file is available in
the man page (man biboumi).&lt;/p&gt;
&lt;p&gt;Biboumi is configured as external component of the XMPP server. In
my case I'm using ejabberd to host my XMPP service. Below is the configuration
needed for allowing biboumi to connect with ejabberd.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;8888&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;127.0.0.1&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ejabberd_service&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;acess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;all&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;biboumi.localhost&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;xxx&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;cite&gt;password&lt;/cite&gt; field in biboumi configuration should match password value in your
XMPP server configuration.&lt;/p&gt;
&lt;p&gt;After doing above configuration reload ejabberd (or your XMPP server) and start
biboumi. Biboumi package provides systemd service file so you might need to
enable it first. That's it now you have an XMPP to IRC gateway ready.&lt;/p&gt;
&lt;p&gt;You might notice that I'm using local host name for &lt;em&gt;hostname&lt;/em&gt; key as well as
&lt;em&gt;ip&lt;/em&gt; field in ejabberd configuration. This is because TLS support was added to
&lt;em&gt;biboumi&lt;/em&gt; Debian package only after 7.2 release as botan 2.x was not available
till that point in Debian. Hence using proper domain name and making biboumi
listen to public will be not safe at least prior to Debian package version
7.2-2. Also making the biboumi service public means you will also need to handle
spam bots trying to connect from your service to IRC, which might get your VPS
banned from IRC.&lt;/p&gt;
&lt;div class="section" id="connection-semantics"&gt;
&lt;h2&gt;Connection Semantics&lt;/h2&gt;
&lt;p&gt;Once biboumi is configured and running you can now use XMPP client of your
choice (Gajim, Conversation etc.) to connect to IRC. To connect to OFTC from
your XMPP client you need to following address in &lt;em&gt;Group Chat&lt;/em&gt; section&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;%irc.oftc.net&amp;#64;biboumi.localhost&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;Replace part after &amp;#64; to what you have configured in &lt;em&gt;hostname&lt;/em&gt; field in biboumi
configuration. To join a specific channel on a IRC server you need to join the
group conversation with following format&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;#channel%irc.example.com&amp;#64;biboumi.localhost&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;If your nick name is registered and you would want to identify yourself to IRC
server you can do that by joining in group conversation with NickServ using
following address&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;nickserv%irc.example.org&amp;#64;biboumi.localhost&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;Once connected you can send NickServ command directly in this virtual channel.
Like &lt;cite&gt;identify password nick&lt;/cite&gt;. It is also possible to configure your XMPP
clients like Gajim to send &lt;a class="reference external" href="https://xmpp.org/extensions/xep-0050.html"&gt;Ad-Hoc commands&lt;/a&gt; on connection to particular IRC
server for identifying your self with IRC servers. But this part I did not get
working in Gajim.&lt;/p&gt;
&lt;p&gt;If you are running your own XMPP server then &lt;em&gt;biboumi&lt;/em&gt; gives you best way to
connect to IRC from your mobile phones. And with applications like
&lt;em&gt;Conversation&lt;/em&gt; running XMPP application won't be hard on your phone battery.&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;ul class="first last simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://lab.louiz.org/louiz/biboumi/blob/master/doc/biboumi.1.rst#configuration"&gt;Biboumi documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://conversations.im/"&gt;Conversations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://docs.ejabberd.im/admin/configuration/"&gt;ejabberd documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
</content><category term="misc"/><category term="xmpp"/><category term="irc"/><category term="gateway"/><category term="mobile"/></entry><entry><title>My personal Email setup - Notmuch, mbsync, postfix and dovecot</title><link href="https://copyninja.in/blog/email_setup.html" rel="alternate"/><published>2017-12-23T16:43:00+05:30</published><updated>2017-12-23T16:43:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-12-23:/blog/email_setup.html</id><summary type="html">&lt;p class="first last"&gt;Brief description of my email setup.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I've been using personal email setup for quite long and have not documented it
anywhere. Recently when I changed my laptop (a post is pending about it) I got
lost trying to recreate my local mail setup. So this post is a self
documentation so that I don't have to struggle again to get it right.&lt;/p&gt;
&lt;div class="section" id="server-side"&gt;
&lt;h2&gt;Server Side&lt;/h2&gt;
&lt;p&gt;I run my own mail server and I use &lt;em&gt;postfix&lt;/em&gt; as SMTP server and &lt;em&gt;Dovecot&lt;/em&gt; for
the IMAP purpose. I'm not going into detail of setting those up as my setup was
mostly done by using scripts created by Jonas for &lt;em&gt;Redpill&lt;/em&gt; infrastructure. What
redpill is?. (In jonas's own words)&lt;/p&gt;
&lt;blockquote&gt;
&amp;lt;jonas&amp;gt; Redpill is a concept - a way to setup Debian hosts to collaborate
across organisations
&amp;lt;jonas&amp;gt; I develop the concept, and use it for the first ever Redpill
network-of-networks redpill.dk, involving my own network (jones.dk), my main
client's network (homebase.dk), a network in Germany including Skolelinux
Germany (free-owl.de), and Vasudev's network (copyninja.info)&lt;/blockquote&gt;
&lt;p&gt;Along with that I have a dovecot sieve filtering to classify on high level mails
into various folders depending on from where they originate. All the rules live
in the &lt;cite&gt;~/dovecot.sieve&lt;/cite&gt; file under every account which has a mail address.&lt;/p&gt;
&lt;p&gt;Again I'm not going into detail of how to set these things up, as its not goal
of my this post.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="on-my-laptop"&gt;
&lt;h2&gt;On my Laptop&lt;/h2&gt;
&lt;p&gt;On my laptop I've following 4 parts setup&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Mail syncing : Done using mbsync command&lt;/li&gt;
&lt;li&gt;Classification: Done using notmuch&lt;/li&gt;
&lt;li&gt;Reading: Done using notmuch-emacs&lt;/li&gt;
&lt;li&gt;Mail sending: Done using postfix running as relay server and SMTP client.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="mail-syncing"&gt;
&lt;h2&gt;Mail Syncing&lt;/h2&gt;
&lt;p&gt;Mail syncing is done using &lt;cite&gt;mbsync&lt;/cite&gt; tool, I was previously user of offlineimap
and recently switched to &lt;cite&gt;mbsync&lt;/cite&gt; as I felt it more lighter and simpler to
configure than &lt;cite&gt;offlineimap&lt;/cite&gt;. &lt;cite&gt;mbsync&lt;/cite&gt; command is provided by package &lt;cite&gt;isync&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Configuration file is &lt;em&gt;~/.mbsyncrc&lt;/em&gt;. Below is my sample content with some
private things redacted.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;IMAPAccount  copyninja&lt;/span&gt;
&lt;span class="na"&gt;Host imap.copyninja.info&lt;/span&gt;
&lt;span class="na"&gt;User vasudev&lt;/span&gt;
&lt;span class="na"&gt;PassCmd      &amp;quot;gpg -q --for-your-eyes-only --no-tty --exit-on-status-write-error --batch --passphrase-file ~/path/to/passphrase.txt -d ~/path/to/mailpass.gpg&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;SSLType IMAPS&lt;/span&gt;
&lt;span class="na"&gt;SSLVersion TLSv1.2&lt;/span&gt;
&lt;span class="na"&gt;CertificateFile /etc/ssl/certs/ca-certificates.crt&lt;/span&gt;


&lt;span class="na"&gt;IMAPAccount gmail-kamathvasudev&lt;/span&gt;
&lt;span class="na"&gt;Host imap.gmail.com&lt;/span&gt;
&lt;span class="na"&gt;User kamathvasudev@gmail.com&lt;/span&gt;
&lt;span class="na"&gt;PassCmd &amp;quot;gpg -q --for-your-eyes-only --no-tty --exit-on-status-write-error --batch --passphrase-file ~/path/to/passphrase.txt -d ~/path/to/mailpass.gpg&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;SSLType IMAPS&lt;/span&gt;
&lt;span class="na"&gt;SSLVersion TLSv1.2&lt;/span&gt;
&lt;span class="na"&gt;CertificateFile /etc/ssl/certs/ca-certificates.crt&lt;/span&gt;

&lt;span class="na"&gt;IMAPStore copyninja-remote&lt;/span&gt;
&lt;span class="na"&gt;Account copyninja&lt;/span&gt;

&lt;span class="na"&gt;IMAPStore gmail-kamathvasudev-remote&lt;/span&gt;
&lt;span class="na"&gt;Account gmail-kamathvasudev&lt;/span&gt;

&lt;span class="na"&gt;MaildirStore copyninja-local&lt;/span&gt;
&lt;span class="na"&gt;Path ~/Mail/vasudev-copyninja.info/&lt;/span&gt;
&lt;span class="na"&gt;Inbox ~/Mail/vasudev-copyninja.info/INBOX&lt;/span&gt;

&lt;span class="na"&gt;MaildirStore gmail-kamathvasudev-local&lt;/span&gt;
&lt;span class="na"&gt;Path ~/Mail/Gmail-1/&lt;/span&gt;
&lt;span class="na"&gt;Inbox ~/Mail/Gmail-1/INBOX&lt;/span&gt;

&lt;span class="na"&gt;Channel copyninja&lt;/span&gt;
&lt;span class="na"&gt;Master&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;copyninja-remote:&lt;/span&gt;
&lt;span class="na"&gt;Slave&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;copyninja-local:&lt;/span&gt;
&lt;span class="na"&gt;Patterns *&lt;/span&gt;
&lt;span class="na"&gt;Create Both&lt;/span&gt;
&lt;span class="na"&gt;SyncState *&lt;/span&gt;
&lt;span class="na"&gt;Sync All&lt;/span&gt;

&lt;span class="na"&gt;Channel gmail-kamathvasudev&lt;/span&gt;
&lt;span class="na"&gt;Master&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;gmail-kamathvasudev-remote:&lt;/span&gt;
&lt;span class="na"&gt;Slave&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;gmail-kamathvasudev-local:&lt;/span&gt;
&lt;span class="c1"&gt;# Exclude everything under the internal [Gmail] folder, except the interesting folders&lt;/span&gt;
&lt;span class="na"&gt;Patterns * ![Gmail]*&lt;/span&gt;
&lt;span class="na"&gt;Create Both&lt;/span&gt;
&lt;span class="na"&gt;SyncState *&lt;/span&gt;
&lt;span class="na"&gt;Sync All&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Explanation for some interesting part in above configuration. One is the
&lt;em&gt;PassCmd&lt;/em&gt; which allows you to provide shell command to obtain the password for
the account. This avoids filling in the password in configuration file. I'm
using symmetric encryption with gpg and storing password some where on my disk.
Which is of course just safe guarded by Unix ACL.&lt;/p&gt;
&lt;p&gt;I actually wanted to use my public key to encrypt the file but unlocking the
file when script is run in background or via systemd looks difficult (or looked
nearly impossible). If you have better suggestion I'm all ears :-).&lt;/p&gt;
&lt;p&gt;Next instruction part is &lt;em&gt;Patterns&lt;/em&gt;. This allows you to selectively sync mail
from your mail server. This was really helpful for me to exclude all crappy
&lt;em&gt;[Gmail]/&lt;/em&gt; folders.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="mail-classification"&gt;
&lt;h2&gt;Mail Classification&lt;/h2&gt;
&lt;p&gt;Once mail is locally on your device, we need a way to read the mails easily in a
mail reader. My original setup was serving synced &lt;em&gt;Maildir&lt;/em&gt; using local dovecot
instance and read it in &lt;em&gt;Gnus&lt;/em&gt;. This setup was bit of a over kill with all
server software setups but inability of Gnus to not cope well with &lt;em&gt;Maildir&lt;/em&gt;
format this was best way to do it. This setup also has a disadvantage, that is
searching a mail quickly when you have huge pile of mail to go through. This is
where &lt;em&gt;notmuch&lt;/em&gt; comes into picture.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;notmuch&lt;/em&gt; allows me to easily index through Gigabytes of my mail archives and
get what I need very easily. I've created a small script which combines
executing of &lt;cite&gt;mbsync&lt;/cite&gt; and &lt;cite&gt;notmuch&lt;/cite&gt; execution. I tag mails based on the Maildirs
which are actually created on server side using dovecot sieve. Below is my full
shell script which is doing task of syncing classification and deleting of
spams.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nv"&gt;MBSYNC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;pgrep&lt;span class="w"&gt; &lt;/span&gt;mbsync&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;NOTMUCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;pgrep&lt;span class="w"&gt; &lt;/span&gt;notmuch&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$MBSYNC&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$NOTMUCH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Already running one instance of mail-sync. Exiting...&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Deleting messages tagged as *deleted*&amp;quot;&lt;/span&gt;
notmuch&lt;span class="w"&gt; &lt;/span&gt;search&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;text0&lt;span class="w"&gt; &lt;/span&gt;--output&lt;span class="o"&gt;=&lt;/span&gt;files&lt;span class="w"&gt; &lt;/span&gt;tag:deleted&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;xargs&lt;span class="w"&gt; &lt;/span&gt;-0&lt;span class="w"&gt; &lt;/span&gt;--no-run-if-empty&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-v

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Moving spam to Spam folder&amp;quot;&lt;/span&gt;
notmuch&lt;span class="w"&gt; &lt;/span&gt;search&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;text0&lt;span class="w"&gt; &lt;/span&gt;--output&lt;span class="o"&gt;=&lt;/span&gt;files&lt;span class="w"&gt; &lt;/span&gt;tag:Spam&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;to:vasudev@copyninja.info&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;xargs&lt;span class="w"&gt; &lt;/span&gt;-0&lt;span class="w"&gt; &lt;/span&gt;-I&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--no-run-if-empty&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/Mail/vasudev-copyninja.info/Spam/cur
notmuch&lt;span class="w"&gt; &lt;/span&gt;search&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;text0&lt;span class="w"&gt; &lt;/span&gt;--output&lt;span class="o"&gt;=&lt;/span&gt;files&lt;span class="w"&gt; &lt;/span&gt;tag:Spam&lt;span class="w"&gt; &lt;/span&gt;and
&lt;span class="w"&gt;  &lt;/span&gt;to:vasudev-debian@copyninja.info&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;xargs&lt;span class="w"&gt; &lt;/span&gt;-0&lt;span class="w"&gt; &lt;/span&gt;-I&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--no-run-if-empty&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/Mail/vasudev-copyninja.info/Spam/cur


&lt;span class="nv"&gt;MDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vasudev-copyninja.info vasudev-debian Gmail-1&amp;quot;&lt;/span&gt;
mbsync&lt;span class="w"&gt; &lt;/span&gt;-Va
notmuch&lt;span class="w"&gt; &lt;/span&gt;new

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mdir&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$MDIR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Processing &lt;/span&gt;&lt;span class="nv"&gt;$mdir&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;fdir&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;/home/vasudev/Mail/&lt;span class="nv"&gt;$mdir&lt;/span&gt;/*&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$fdir&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;INBOX&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tagging for &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$fdir&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;notmuch&lt;span class="w"&gt; &lt;/span&gt;tag&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$fdir&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-inbox&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;folder:&lt;span class="nv"&gt;$mdir&lt;/span&gt;/&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$fdir&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So before running mbsync I search for all mails tagged as &lt;em&gt;deleted&lt;/em&gt; and delete
them from system. Next I look for mails tagged as &lt;em&gt;Spam&lt;/em&gt; on both my accounts and
move it to Spam folder. Yeah you got it right these are mails escaping the spam
filter and landing in my inbox and personally marked as Spam.&lt;/p&gt;
&lt;p&gt;After running mbsync I tag mails based on their folder (searching string
&lt;em&gt;folder:&lt;/em&gt;). This allows me easily get contents of lets say a mailing list
without remembering the list address.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="reading-mails"&gt;
&lt;h2&gt;Reading Mails&lt;/h2&gt;
&lt;p&gt;Now that we have synced and classified mail its time to setup the reading part.
I use notmuch-emacs interface to read the mails. I use &lt;em&gt;Spacemacs&lt;/em&gt; flavor of
emacs so I took some time to write down the a private layer which brings
together all my keybindings and classification in one place and does not clutter
my entire &lt;em&gt;.spacemacs&lt;/em&gt; file. You can find the code for my private layer in
&lt;a class="reference external" href="https://source.copyninja.info/notmuch-emacs-layer.git/"&gt;notmuch-emacs-layer repository&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="sending-mails"&gt;
&lt;h2&gt;Sending Mails&lt;/h2&gt;
&lt;p&gt;Well its not sufficient that if we can read mails, we need to be able to reply
to mail. And this was the slightly tricky part where I recently got lost and had
to write this post so that I don't forget it again. (And of course don't have to
refer some outdated posts on web).&lt;/p&gt;
&lt;p&gt;My setup to send mails is using &lt;em&gt;postfix&lt;/em&gt; as SMTP client with my own SMTP server
as relayhost for it. The problem of relaying is it's not for the hosts with
dynamic IP. There are couple of ways to allow hosts with dynamic IP to use relay
servers, one is put the IP address from where mail will originate into
&lt;em&gt;my_network&lt;/em&gt; or second use SASL authentication.&lt;/p&gt;
&lt;p&gt;My preferred way is use of SASL authentication. For this I first had to create a
separate account one for each machine which is going to relay the mails to my
main server. Idea is to not use my primary account for SASL authentication.
(Originally I was using primary account, but Jonas gave this idea of account per
road runner).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;adduser&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;hostname&amp;gt;_relay
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here replace &amp;lt;hostname&amp;gt; with name of your laptop/desktop or whatever you are
using. Now we need to adjust postfix to act as relaying server. So add following
lines to postfix configuration&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# SASL authentication&lt;/span&gt;
&lt;span class="na"&gt;smtp_sasl_auth_enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;smtp_tls_security_level&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;encrypt&lt;/span&gt;
&lt;span class="na"&gt;smtp_sasl_tls_security_options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;noanonymous&lt;/span&gt;
&lt;span class="na"&gt;relayhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;[smtp.copyninja.info]:submission&lt;/span&gt;
&lt;span class="na"&gt;smtp_sasl_password_maps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;hash:/etc/postfix/sasl_passwd&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So here relayhost is the server name which your postfix instance will be using
to relay mails forward into internet. &lt;em&gt;:submission&lt;/em&gt; part tells postfix to
forward mail on to port 587 (secure). &lt;em&gt;smtp_sasl_tls_security_options&lt;/em&gt; is set to
disallow anonymous connection. This is must so that relay server trusts your
mobile host and agrees to forward the mail for you.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;/etc/postfix/sasl_passwd&lt;/em&gt; is the file where you need to store password for
account to be used for SASL authentication with server. Put following content
into it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;[smtp.example.com]:submission    user:password
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Replace smtp.example.com with your SMTP server name which you have put in
&lt;em&gt;relayhost&lt;/em&gt; configuration. Replace user with &amp;lt;hostname&amp;gt;_relay user you created
and its password.&lt;/p&gt;
&lt;p&gt;To secure the sasl_passwd file and create a hash of it for postfix use following
command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;root:root&lt;span class="w"&gt; &lt;/span&gt;/etc/postfix/sasl_passwd
chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/postfix/sasl_passwd
postmap&lt;span class="w"&gt; &lt;/span&gt;/etc/postfix/sasl_passwd
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last command will create /etc/postfix/sasl_passwd.db file which is hash of
your file /etc/postfix/sasl_passwd with same owner and permission. Now reload
the postfix and check if mail makes out of your system using mail command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="bonus-part"&gt;
&lt;h2&gt;Bonus Part&lt;/h2&gt;
&lt;p&gt;Well since I've a script created above bringing together mail syncing and
classification. I went ahead and created a systemd timer to periodically sync
mails in the background. In my case every 10 minutes. Below is &lt;em&gt;mailsync.timer&lt;/em&gt;
file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Check Mail Every 10 minutes&lt;/span&gt;
&lt;span class="na"&gt;RefuseManualStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="na"&gt;RefuseManualStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;

&lt;span class="k"&gt;[Timer]&lt;/span&gt;
&lt;span class="na"&gt;Persistent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;OnBootSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5min&lt;/span&gt;
&lt;span class="na"&gt;OnUnitActiveSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10min&lt;/span&gt;
&lt;span class="na"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mailsync.service&lt;/span&gt;

&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;default.target&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Below is &lt;em&gt;mailsync.service&lt;/em&gt; which is needed by mailsync.timer to execute our
scripts.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Check Mail&lt;/span&gt;
&lt;span class="na"&gt;RefuseManualStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="na"&gt;RefuseManualStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;oneshot&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/mail-sync&lt;/span&gt;
&lt;span class="na"&gt;StandardOutput&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;syslog&lt;/span&gt;
&lt;span class="na"&gt;StandardError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;syslog&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Put these files under /etc/systemd/user and run below command to enable them.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;mailsync.timer
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;mailsync.service
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;mailsync.timer
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So that's how I've sync and send mail from my system. I came to know about
&lt;em&gt;afew&lt;/em&gt; from Jonas Smedegaard who also proof read this post. So next step I will
try to improve my notmuch configuration using afew and of course a post will
follow after that :-).&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="email"/><category term="notmuch"/><category term="mbsync"/></entry><entry><title>Writing a UDP Broadcast Receiver as Python Iterator</title><link href="https://copyninja.in/blog/udp-server-as-generator.html" rel="alternate"/><published>2017-08-19T18:58:00+05:30</published><updated>2017-08-19T18:58:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-08-19:/blog/udp-server-as-generator.html</id><summary type="html">&lt;p class="first last"&gt;Post explaining my experiment of writing a UDP Broadcast Receiving
service as a Python iterator.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I had to write a small Python application to listen for some broadcast message
and process the message. This broadcast messages are actually sort of discovery
messages to find some peers in a network. Writing a simple UDP Server to listen
on a particular port was easy; but while designing an application I was
wondering how can I plugin this server into my main code. There are 2
possibility&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Use threading module of python to send the server code in back ground and
give it a callback to communicate the data to main thread.&lt;/li&gt;
&lt;li&gt;Periodically read some messages from server code and then dispose of server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I didn't like first approach because I need to pass a callback function and I
some how will end up complicating code. Second approach sounded sane but I did
want to make server more like &lt;em&gt;iterator&lt;/em&gt;. I searched around to see if some one
has attempted to write something similar, but did not find anything useful (may
be my Googling skills aren't good enough). Anyway so I thought what is wrong in
trying?. If it works then I'll be happy that I did something different :-).&lt;/p&gt;
&lt;p&gt;The first thing for making iterator in Python is having function &lt;cite&gt;__iter__&lt;/cite&gt; and
&lt;cite&gt;__next__&lt;/cite&gt; defined in your class. For Python 2 iterator protocol wanted &lt;cite&gt;next&lt;/cite&gt;
to be defined instead of &lt;cite&gt;__next__&lt;/cite&gt;. So for portable code you can define a
&lt;cite&gt;next&lt;/cite&gt; function which in return calls &lt;cite&gt;__next__&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;So here is my first shot at writing &lt;cite&gt;BroadCastReceiver&lt;/cite&gt; class.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SOCK_DGRAM&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BroadCastReceiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SOCK_DGRAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setsockopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SOL_SOCKET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SO_REUSEADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msg_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg_len&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__iter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__next__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
             &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                 &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recvfrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msg_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
             &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                 &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Got exception trying to recv &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                 &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;StopIteration&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This version of code can be used in a &lt;cite&gt;for&lt;/cite&gt; loop to read from socket UDP
broadcasts. One problem will be that if no packet is received which might be due
to disconnected network the loop will just block forever. So I had to modify the
code slightly to add timeout parameter. So changed portion of code is below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SOCK_DGRAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setsockopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SOL_SOCKET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SO_REUSEADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msg_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg_len&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

 &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So now if network is disconnected or no packet was received for &lt;cite&gt;timeout&lt;/cite&gt; period
we get a &lt;cite&gt;socket.timeout&lt;/cite&gt; exception due to which &lt;cite&gt;StopIteration&lt;/cite&gt; will be raised
causing the &lt;cite&gt;for&lt;/cite&gt; loop using server as iterator to exit. This avoids us just
blocking our periodic code run forever when network is disconnected or no
messages are received for long time. (may be due to connected to wrong network).&lt;/p&gt;
&lt;p&gt;Now every thing looks fine but only part is if we create the server object each
time our periodic code is called we will have binding issue as we did not
properly close the socket once iterator has stopped. So I added socket closing
code in &lt;cite&gt;__del__&lt;/cite&gt; function for the class. &lt;cite&gt;__del__&lt;/cite&gt; will be called when garbage
collector try to recollect object when it goes out of scope.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__del__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So the server can be used in &lt;cite&gt;for&lt;/cite&gt; loop or by passing the object of server to
&lt;cite&gt;next&lt;/cite&gt; built-in function. Here are 2 examples.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BroadCastReceiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Got packet from &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="c1"&gt;# do whatever you want with data&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we use an counter variable to track iteration and after some iteration we
exit for loop. Another way is use &lt;cite&gt;for&lt;/cite&gt; loop with range of iteration like below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BroadCastReceiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# do whatever you want with data&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here an additional try block was needed inside the for loop to card call to
&lt;cite&gt;next&lt;/cite&gt;, this is to handle the timeout or other exception and exit the loop. In
first case this is not needed as &lt;cite&gt;StopIteration&lt;/cite&gt; is understood by &lt;cite&gt;for&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Both use cases I described above are mostly useful when it is not critical to
handle each and every packet (mostly peer discovery) and packets will always be
sent. So if we miss some peers in one iteration we will still catch them in next
iteration. We just need to make sure we provide big enough counter to catch most
peers in each iteration.&lt;/p&gt;
&lt;p&gt;If its critical to receive each packet we can safely send this iterating logic
to a separate thread which keeps receiving packets and process data as needed.&lt;/p&gt;
&lt;p&gt;For now I tried this pattern mostly with UDP protocol but I'm sure with some
modification this can be used with TCP as well. I'll be happy to get feed back
from Pythonistas out there on what you think of this approach. :-)&lt;/p&gt;
&lt;div class="section" id="update"&gt;
&lt;h2&gt;Update&lt;/h2&gt;
&lt;p&gt;I got a suggestion from &lt;em&gt;Ryan Nowakowski&lt;/em&gt; to make the server object as &lt;cite&gt;context
manager&lt;/cite&gt; and close the socket in &lt;cite&gt;__exit__&lt;/cite&gt; as it can't be guaranteed that
&lt;cite&gt;__del__&lt;/cite&gt; will be called for objects which exists during interpreter exits. So I
slightly modified the class to add &lt;cite&gt;__enter__&lt;/cite&gt; and &lt;cite&gt;__exit__&lt;/cite&gt; method like below
and removed &lt;cite&gt;__del__&lt;/cite&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usage pattern is slightly modified because of this and we need to use &lt;cite&gt;with&lt;/cite&gt;
statement while creating object.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;BroadCastReceiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# use server object as you wish&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is also possible to cleanly close socket without adding context manager that
is adding &lt;cite&gt;finally&lt;/cite&gt; statement to our &lt;cite&gt;try&lt;/cite&gt; and &lt;cite&gt;except&lt;/cite&gt; block in &lt;cite&gt;__next__&lt;/cite&gt;. The
modified code without adding context manager looks like below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__next__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recvfrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msg_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Got exception trying to recv &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;StopIteration&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we raise &lt;cite&gt;StopIteration&lt;/cite&gt; again from except block, it will be temporarily
saved and &lt;cite&gt;finally&lt;/cite&gt; block is executed which will now close the socket.&lt;/p&gt;
&lt;/div&gt;
</content><category term="development"/><category term="python"/><category term="iterators"/><category term="udp server"/></entry><entry><title>Overriding version information from setup.py with pbr</title><link href="https://copyninja.in/blog/override-version-pbr.html" rel="alternate"/><published>2017-07-16T20:53:00+05:30</published><updated>2017-07-16T20:53:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-07-16:/blog/override-version-pbr.html</id><summary type="html">&lt;p class="first last"&gt;Post to explain a workaround I did to override version information
detected by pbr for zfec upstream.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I recently raised a &lt;a class="reference external" href="https://github.com/tahoe-lafs/zfec/pull/5"&gt;pull request&lt;/a&gt;
on zfec for converting its python packaging from pure &lt;cite&gt;setup.py&lt;/cite&gt; to &lt;cite&gt;pbr&lt;/cite&gt; based.
Today I got review from &lt;em&gt;Brian Warner&lt;/em&gt; and one of the issue mentioned was
&lt;cite&gt;python setup.py --version&lt;/cite&gt; is not giving same output as previous version of
&lt;cite&gt;setup.py&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Previous version used &lt;a class="reference external" href="https://github.com/warner/python-versioneer"&gt;versioneer&lt;/a&gt; which extracts version
information needed from VCS tags. Versioneer also provides flexibility of
specifying type of VCS used, style of version, tag prefix (for VCS) etc. &lt;cite&gt;pbr&lt;/cite&gt;
also does extract version information from git tag but it expects git tag to be
of format &lt;em&gt;tags/refs/x.y.z&lt;/em&gt; format but &lt;em&gt;zfec&lt;/em&gt; used a &lt;cite&gt;zfec-&lt;/cite&gt; prefix to tag
(example &lt;em&gt;zfec-1.4.24&lt;/em&gt;) and &lt;em&gt;pbr&lt;/em&gt; does not process this. End result, I get a
version in format &lt;em&gt;0.0.devNN&lt;/em&gt; where &lt;em&gt;NN&lt;/em&gt; is number of commits in the repository
from its inception.&lt;/p&gt;
&lt;p&gt;Me and Brian spent few hours trying to figure out a way to tell pbr that we
would like to override version information it auto deduces, but there was none
other than putting version string in &lt;cite&gt;PBR_VERSION&lt;/cite&gt; environment variable. That
documentation was contributed by me &lt;a class="reference external" href="https://github.com/openstack-dev/pbr/commit/007f4ee2abf818b4b18b6e8347da1d4eb2e0ad9c"&gt;3 years back to pbr project.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So finally I used &lt;cite&gt;versioneer&lt;/cite&gt; to create a version string and put it in the
environment variable &lt;em&gt;PBR_VERSION&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;versioneer&lt;/span&gt;

&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;PBR_VERSION&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;versioneer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_version&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;setup_requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pbr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;pbr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ext_modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;extensions&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And added below snippet to &lt;em&gt;setup.cfg&lt;/em&gt; which is how versioneer can be configured
with various information including tag prefixes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[versioneer]&lt;/span&gt;
&lt;span class="na"&gt;VCS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;
&lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;pep440&lt;/span&gt;
&lt;span class="na"&gt;versionfile_source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;zfec/_version.py&lt;/span&gt;
&lt;span class="na"&gt;versionfile_build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;zfec/_version.py&lt;/span&gt;
&lt;span class="na"&gt;tag_prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;zfec-&lt;/span&gt;
&lt;span class="na"&gt;parentdir_prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;zfec-&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Though this work around gets the work done, it does not feel correct to set
environment variable to change the logic of other part of same program. If you
guys know the better way do let me know!. Also probably I should consider filing
an feature request against &lt;cite&gt;pbr&lt;/cite&gt; to provide a way to pass tag prefix for version
calculation logic.&lt;/p&gt;
</content><category term="development"/><category term="python"/><category term="pbr"/><category term="zfec"/></entry><entry><title>debcargo: Replacing subprocess crate with git2 crate</title><link href="https://copyninja.in/blog/using-git2-debcargo.html" rel="alternate"/><published>2017-07-15T15:35:00+05:30</published><updated>2017-07-15T15:35:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-07-15:/blog/using-git2-debcargo.html</id><summary type="html">&lt;p class="first last"&gt;Replace shell calls in debcargo to extract git information with git2
library crate.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my previous &lt;a class="reference external" href="https://copyninja.info/blog/shell-pipelines-rust.html"&gt;post&lt;/a&gt; I
talked about using &lt;em&gt;subprocess&lt;/em&gt; crate to extract beginning and ending year from
git repository for generating debian/copyright file. In this post I'm going to
talk on how I replaced &lt;em&gt;subprocess&lt;/em&gt; with native &lt;em&gt;git2&lt;/em&gt; crate and achieved the
same result in much cleaner and safer way.&lt;/p&gt;
&lt;p&gt;git2 is a native Rust crate which provides access to Git repository internals.
git2 does not involve any &lt;em&gt;unsafe&lt;/em&gt; invocation as it is built against
&lt;em&gt;libgit2-sys&lt;/em&gt; which is actually using Rust FFI to directly bind to underlying
libgit library. Below is the new &lt;em&gt;copyright_fromgit&lt;/em&gt; function with git2 crate.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;copyright_fromgit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TempDir&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;debcargo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;revwalker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;revwalk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;revwalker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// Get the latest and first commit id. This is bit ugly&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;latest_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;revwalker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;revwalker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// revwalker ends here is consumed by last&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first_commit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;latest_commit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first_year&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Utc&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_utc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;NaiveDateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_commit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;Utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;latest_year&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Utc&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_utc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;NaiveDateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest_commit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;Utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first_year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;latest_year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first_year&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}-{},&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first_year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;latest_year&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;So here is what I'm doing&lt;/dt&gt;
&lt;dd&gt;&lt;ol class="first last arabic simple"&gt;
&lt;li&gt;Use &lt;cite&gt;git2::Repository::clone&lt;/cite&gt; to clone the given URL. We are thus avoiding
exec of &lt;em&gt;git clone&lt;/em&gt; command.&lt;/li&gt;
&lt;li&gt;Get a revision walker object. &lt;cite&gt;git2::RevWalk&lt;/cite&gt; implements &lt;cite&gt;Iterator&lt;/cite&gt; trait
and allows walking through the git history. This is what we are using to
avoid exec of &lt;em&gt;git log&lt;/em&gt; command.&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;revwalker.push_head()&lt;/cite&gt; is important because we want to tell revwalker from
where we want to walk the history. In this case we are asking it to walk
history from repository HEAD. Without this line next line will not work.
(Learned it in hard way :-) ).&lt;/li&gt;
&lt;li&gt;Then we extract &lt;cite&gt;git2::Oid&lt;/cite&gt; which is we can say similar to commit hash and
can be used to lookup a particular commit. We take latest commit hash using
&lt;cite&gt;RevWalk::next&lt;/cite&gt; call and the first commit using &lt;cite&gt;Revwalk::last&lt;/cite&gt;, note the
order this is because &lt;cite&gt;Revwalk::last&lt;/cite&gt; consumes the revwalker so doing it in
reverse order will make borrow checker unhappy :-). This replaces exec of
&lt;cite&gt;head -n1&lt;/cite&gt; command.&lt;/li&gt;
&lt;li&gt;Look up the &lt;cite&gt;git2::Commit&lt;/cite&gt; objects using &lt;cite&gt;git2::Repository::find_commit&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Then  convert the &lt;cite&gt;git2::Time&lt;/cite&gt; to &lt;cite&gt;chrono::DateTime&lt;/cite&gt; and take out the years.&lt;/li&gt;
&lt;/ol&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;After this change I found an obvious error which went unnoticed in previous
version, that is if there was no &lt;em&gt;repository&lt;/em&gt; key in Cargo.toml. When there was
no repo URL &lt;em&gt;git clone&lt;/em&gt; exec did not error out and our shell commands happily
extracted year from the &lt;em&gt;debcargo&lt;/em&gt; repository!. Well since I was testing code
from &lt;em&gt;debcargo&lt;/em&gt; repository It never failed, but when I executed from non-git
repository folder git threw an error but that was &lt;em&gt;git log&lt;/em&gt; and not &lt;em&gt;git
clone&lt;/em&gt;. This error was spotted right away because git2 threw me an error that I
gave it empty URL.&lt;/p&gt;
&lt;p&gt;When it comes to performance I see that debcargo is faster compared to previous
version. This makes sense because previously it was doing 5 fork and exec system
calls and now that is avoided.&lt;/p&gt;
</content><category term="development"/><category term="rust"/><category term="subprocess"/><category term="git"/></entry><entry><title>Update: - Shell pipelines with subprocess crate and use of Exec::shell function</title><link href="https://copyninja.in/blog/update-shell-pipelines.html" rel="alternate"/><published>2017-06-19T20:48:00+05:30</published><updated>2017-06-19T20:48:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-06-19:/blog/update-shell-pipelines.html</id><summary type="html">&lt;p class="first last"&gt;Update to my previous post on using Exec::shell from subprocess crates
to create shell pipeline.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my &lt;a class="reference external" href="https://copyninja.info/blog/shell-pipelines-rust.html"&gt;previous post&lt;/a&gt; I
used &lt;cite&gt;Exec::shell&lt;/cite&gt; function from subprocess crate and passed it string generated
by interpolating &lt;em&gt;--author&lt;/em&gt; argument. This string was then run by the shell via
&lt;cite&gt;Exec::shell&lt;/cite&gt;. After publishing post I got ping on IRC by &lt;a class="reference external" href="https://wiki.debian.org/JonasSmedegaard"&gt;Jonas Smedegaard&lt;/a&gt; and &lt;a class="reference external" href="https://wiki.debian.org/PaulWise"&gt;Paul Wise&lt;/a&gt; that I should replace &lt;cite&gt;Exec::shell&lt;/cite&gt;, as it
might be prone to errors or vulnerabilities of shell injection attack. Indeed
they were right, in hurry I did not completely read the function documentation
which clearly mentions this fact.&lt;/p&gt;
&lt;blockquote&gt;
When invoking this function, be careful not to interpolate arguments into
the string run by the shell, such as Exec::shell(format!(&amp;quot;sort {}&amp;quot;,
filename)). Such code is prone to errors and, if filename comes from an
untrusted source, to shell injection attacks. Instead, use
Exec::cmd(&amp;quot;sort&amp;quot;).arg(filename).&lt;/blockquote&gt;
&lt;p&gt;Though I'm not directly taking input from untrusted source, its still possible
that the string I got back from git log command might contain some oddly
formatted string with characters of different encoding which could possibly
break the &lt;cite&gt;Exec::shell&lt;/cite&gt; , as I'm not sanitizing the shell command. When we use
&lt;cite&gt;Exec::cmd&lt;/cite&gt; and pass argument using &lt;em&gt;.args&lt;/em&gt; chaining, the library takes care of
creating safe command line. So I went in and modified the function to use
&lt;cite&gt;Exec::cmd&lt;/cite&gt; instead of &lt;cite&gt;Exec::shell&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Below is updated function.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;copyright_fromgit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TempDir&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;debcargo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;git&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;clone&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--bare&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NullFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NullFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;popen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author_process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;git log --format=&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;%an &amp;lt;%ae&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sort -u&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author_process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--author={}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin/git&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--format=%ad&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--date=format:%Y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--reverse&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;author_string&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;head -n1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin/git&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--format=%ad&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--date=format:%Y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;author_string&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;head -n1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cnotice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}, {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}-{}, {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cnotice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I still use &lt;cite&gt;Exec::shell&lt;/cite&gt; for generating author list, this is not problematic as
I'm not interpolating arguments to create command string.&lt;/p&gt;
</content><category term="development"/><category term="rust"/><category term="subprocess"/><category term="shell inejctions"/></entry><entry><title>Rust - Shell like Process pipelines using subprocess crate</title><link href="https://copyninja.in/blog/shell-pipelines-rust.html" rel="alternate"/><published>2017-06-18T20:59:00+05:30</published><updated>2017-06-18T20:59:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-06-18:/blog/shell-pipelines-rust.html</id><summary type="html">&lt;p class="first last"&gt;Post briefly describes running shell command pipelines in Rust using
subprocess crate.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I had to extract copyright information from the git repository of the crate
upstream. The need aroused as part of updating &lt;em&gt;debcargo&lt;/em&gt;, tool to create Debian
package source from the Rust crate.&lt;/p&gt;
&lt;p&gt;General idea behind taking copyright information from git is to extract starting
and latest contribution year for every author/committer. This can be easily
achieved using following shell snippet&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;author&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%an&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sort&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;author_email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%an &amp;lt;%ae&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--author&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$author&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n1&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;first&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;--author&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$author&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--date&lt;span class="o"&gt;=&lt;/span&gt;format:%Y&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%ad&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--reverse&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n1&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;latest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;--author&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$author&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--date&lt;span class="o"&gt;=&lt;/span&gt;format:%Y&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%ad&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n1&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-eq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="nv"&gt;$author_email&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;$latest&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="nv"&gt;$author_email&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now challenge was to execute these command in Rust and get the required answer.
So first step was I looked at &lt;em&gt;std::process&lt;/em&gt;, default standard library support
for executing shell commands.&lt;/p&gt;
&lt;p&gt;My idea was to execute first command to extract authors into a Rust &lt;em&gt;vectors&lt;/em&gt; or
&lt;em&gt;array&lt;/em&gt; and then have 2 remaining command to extract years in a loop. (Yes I do
not need additional author_email command in Rust as I can easily get both in the
first command which is used in for loop of shell snippet and use it inside
another loop). So I setup to 3 commands outside the loop with input and output
redirected, following is snippet should give you some idea of what I tried to do.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors_command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin/git&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--format=&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;%an &amp;lt;%ae&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors_command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_utf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head_n1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin/head&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-n1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Stdio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;piped&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Stdio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;piped&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spwn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And inside the loop I would create additional 2 git commands read their output
via pipe and feed it to head command. This is where I learned that it is not
straight forward as it looks :-). &lt;em&gt;std::process::Command&lt;/em&gt; type does not
implement &lt;em&gt;Copy&lt;/em&gt; nor &lt;em&gt;Clone&lt;/em&gt; traits which means one use of it I will give up the
ownership!. And here I started fighting with borrow checker. I need to duplicate
declarations to make sure I've required commands available all the time.
Additionally I needed to handle error output at every point which created too
many nested statements there by complicating the program and reducing its
readability&lt;/p&gt;
&lt;p&gt;When all started getting out of control I gave a second thought and wondered if
it would be good to write down this in shell script ship it along with debcargo
and use the script Rust program. This would satisfy my need but I would need to
ship additional script along with debcargo which I was not really happy with.&lt;/p&gt;
&lt;p&gt;Then a search on crates.io revealed &lt;em&gt;subprocess&lt;/em&gt;, a crate designed to be similar
with &lt;em&gt;subprocess&lt;/em&gt; module from Python!. Though crate is not highly downloaded it
still looked promising, especially the trait implements a trait called &lt;cite&gt;BitOr&lt;/cite&gt;
which allows use of &lt;cite&gt;|&lt;/cite&gt; operator to chain the commands. Additionally it allows
executing full shell commands without need of additional chaining of argument
which was done above snippet. End result a much simplified easy to read and
correct function which does what was needed. Below is the function I wrote to
extract copyright information from git repo.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;copyright_fromgit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TempDir&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;debcargo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;git clone --bare {} {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                &lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                &lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;                              &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;())).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NullFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                              &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NullFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                              &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;popen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author_process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;git log --format=&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;%an &amp;lt;%ae&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sort -u&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author_process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reverse_command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;git log --author=&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt; --format=%ad --date=format:%Y \&lt;/span&gt;
&lt;span class="s"&gt;                                    --reverse&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                   &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;git log --author=&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt; --format=%ad --date=format:%Y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;reverse_command&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;head -n1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempdir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;head -n1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout_str&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cnotice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}, {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}-{}, {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cnotice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course it is not as short as the shell or probably Python code, but that is
fine as Rust is system level programming language (which is intended to replace
C/C++) and doing complex Shell code (complex due to need of shell pipelines) in
approximately 50 lines of code in safe and secure way is very much acceptable.
Besides code is as much readable as a plain shell snippet thanks to the &lt;cite&gt;|&lt;/cite&gt;
operator implemented by subprocess crate.&lt;/p&gt;
</content><category term="development"/><category term="rust"/><category term="subprocess"/></entry><entry><title>Tips for fuzzing network programs with AFL</title><link href="https://copyninja.in/blog/afl-and-network-programs.html" rel="alternate"/><published>2017-05-07T15:00:00+05:30</published><updated>2017-05-07T15:00:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-05-07:/blog/afl-and-network-programs.html</id><summary type="html">&lt;p class="first last"&gt;Post provide tips on how to successfully fuzz network programs with
AFL (American Fuzzy Lop)&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Fuzzing is method of producing random malformed inputs for a software and
observe the software behavior. If a software crashes then there is a bug and it
can have security implications. Fuzzing has gained a lot of interest now a days,
especially with automated tools like American Fuzzy Lop (AFL) which can easily
help you to fuzz the program and record inputs which causes crash in the
software.&lt;/p&gt;
&lt;p&gt;American Fuzzy Lop is a file based fuzzer which feeds input to program via
standard input. Using it with network program like server's or clients is not
possible in the original state. There is a &lt;a class="reference external" href="https://github.com/jdbirdwell/afl"&gt;version&lt;/a&gt; of AFL with patches to allow it fuzz
network programs, but this patch is not merged upstream and I do not know if it
ever makes into upstream or not. Also the above repository contains version 1.9
which is older compared to currently released versions.&lt;/p&gt;
&lt;p&gt;There is another method for fuzzing network program using AFL with help of
&lt;em&gt;LD_PRELOAD&lt;/em&gt; tricks. &lt;a class="reference external" href="https://github.com/zardus/preeny"&gt;preeny&lt;/a&gt;  is a project
which provides library which when used with LD_PRELOAD can desocket the network
program and make it read from &lt;em&gt;stdin&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There is this best tutorial from &lt;a class="reference external" href="https://lolware.net/2015/04/28/nginx-fuzzing.html"&gt;LoLWare&lt;/a&gt; which talks about fuzzing
Nginx with &lt;em&gt;preeny&lt;/em&gt; and AFL. There is a best AFL workflow by &lt;a class="reference external" href="https://foxglovesecurity.com/2016/03/15/fuzzing-workflows-a-fuzz-job-from-start-to-finish/"&gt;Foxglove Security&lt;/a&gt;
which gives start to finish details about how to use AFL and its companion tool
to do fuzzing. So I'm not going to talk about any steps of fuzzing in this post
instead I'm going to list down my observations on changes that needs to be done
to get clean fuzzing with AFL and preeny.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;desock.so provided by preeny works only with &lt;em&gt;read&lt;/em&gt; and &lt;em&gt;write&lt;/em&gt; (or rather
other system call does not work with stdin) system calls and hence you need
to make sure you replace any reference to &lt;em&gt;send&lt;/em&gt;, &lt;em&gt;sendto&lt;/em&gt;, &lt;em&gt;recv&lt;/em&gt; and
&lt;em&gt;recvfrom&lt;/em&gt; with &lt;em&gt;read&lt;/em&gt; and &lt;em&gt;write&lt;/em&gt; system calls respectively. Without this
change program will not read input provided by AFL on standard input.&lt;/li&gt;
&lt;li&gt;If your network program is using forking or threading model make sure to
remove all those and make it plain simple program which receives request and
sends out response. Basically you are testing the ability of program to
handle malformed input so we need very minimum logic to make program do what
it is supposed to do when AFL runs it.&lt;/li&gt;
&lt;li&gt;If you are using infinite loop like all normal programs replace the infinite
loop with below mentioned AFL macro and use &lt;em&gt;afl-clang-fast&lt;/em&gt; to compile it.
This speeds up the testing as AFL will run the job &lt;cite&gt;n&lt;/cite&gt; times before
discarding the current fork and doing a fresh fork. After all fork is costly
affair.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__AFL_LOOP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Change 1000 with iteration count&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// your logic here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With above modification I could fuzz a server program talking binary protocol
and another one talking textual protocol. In both case I used &lt;em&gt;Wireshark&lt;/em&gt;
capture to get the packet extract raw content and feed it as input to AFL.&lt;/p&gt;
&lt;p&gt;I was successful in finding crashes which are exploitable in case of textual
protocol program than in binary protocol case. In case of binary protocol AFL
could not easily find new paths which probably is because of bad inputs I
provided. I will continue to do more experiment with binary protocol case and
provide my findings as new updates here.&lt;/p&gt;
&lt;p&gt;If you have anything more to add do share with me :-). Happy fuzzing!.&lt;/p&gt;
</content><category term="security"/><category term="AFL"/><category term="fuzzing"/><category term="preeny"/><category term="security"/></entry><entry><title>Magic: Attach a HTML file to mail and get different on other side</title><link href="https://copyninja.in/blog/fun-with-html-encoding.html" rel="alternate"/><published>2017-05-06T13:19:00+05:30</published><updated>2017-05-06T13:19:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2017-05-06:/blog/fun-with-html-encoding.html</id><summary type="html">&lt;p class="first last"&gt;Magic happens when you attach HTML with certain format in mail and
find totally different file on other end.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;It's been a long time I did not write any new blog posts, and finally I got
something which is interesting enough for a new post and so here it is.&lt;/p&gt;
&lt;p&gt;I actually wanted some bills from my ISP for some work and I could not find mail
from the ISP which had bills for some specific months in my mailbox. Problem
with my ISP is bills are accessible in their account which can be only accessed
from their own network. They do have a mobile app and that does not seem to work
especially for the billing section. I used mobile app and selected month for
which I did not have bill and clicked &lt;em&gt;Send Mail&lt;/em&gt; button. App happily showed
message saying it sent the bill to my registered mail address but that was a
fancy lie. After trying several time I gave up and decided I will do it once I
get back home.&lt;/p&gt;
&lt;p&gt;Fast forward few hours, I'm back home from office and then I sat in front of my
laptop and connected to ISP site, promptly downloaded the bills, then used
&lt;em&gt;notmuch-emacs&lt;/em&gt; and fire up a mail composer, attach those HTML file (yeah they
produce bill in HTML file :-/) send it to my gmail and forget about it.&lt;/p&gt;
&lt;p&gt;Fast forward few more days, I just remember I need those bills. I got hold of
mail I sent earlier in gmail inbox and clicked on attachment and when browser
opened the attachment I was shocked/surprised . Did you ask why?. See what I saw
when I opened attachment.&lt;/p&gt;
&lt;img alt="" src="https://copyninja.in/images/converted_html.png" /&gt;
&lt;p&gt;Well I was confused for moment on what happened, I tried downloading the file
and opened it an editor, and I see Chinese characters here also. After reaching
home I checked the Sent folder in my laptop where I keep copy of mails sent
using &lt;em&gt;notmuch-emacs&lt;/em&gt;'s &lt;cite&gt;notmuch-fcc-dirs&lt;/cite&gt; variable. I open the file and open
the attachement and I see same character as I saw in browser!. I open the
original bills I downloaded and it looks fine. To check if I really attached the
correct files I again drafted a mail this time to my personal email and sent it.
Now I open the file from Sent folder and voila again there is different content
inside my attachment!. Same happens when I receive the mail and open the
attachment everything inside is Chinese characters!. Totally lost I finally
opened the original file using &lt;em&gt;emacs&lt;/em&gt;, since I use &lt;em&gt;spacemacs&lt;/em&gt; it asked me for
downloading of &lt;em&gt;html layer&lt;/em&gt; and after which I was surprised because everything
inside the editor is in Chinese!. OK finally I've something now so I opened same
file at same time in &lt;em&gt;nano&lt;/em&gt; from terminal and there it looks fine!. OK that is
weird again I read carefully content and saw this line in beginning of file&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-16&amp;quot; ?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/1999/xhtml&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;....
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;OK that is new XML tag had encoding declared as &lt;em&gt;UTF-16&lt;/em&gt;, really?. And just for
checking I changed it to UTF-8 and voila file is back to normal in Emacs
window!. To confirm this behavior I created a sample file with following content&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/html; charset=iso-8859-1&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Something weird &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;blablablablablalabkabakba&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Yeah with long line because ISP had similar case and now I opened the same file
in nano using terminal and changed &lt;cite&gt;encoding=&amp;quot;UTF-8&amp;quot;&lt;/cite&gt; to &lt;cite&gt;encoding=&amp;quot;UTF-16&amp;quot;&lt;/cite&gt; and
the behavior repeated I see Chinese character in the emacs buffer which has also
opened the same file.&lt;/p&gt;
&lt;p&gt;Below is the small gif showing this happening in real time, see what happens in
emacs buffer when I change the encoding in terminal below. Fun right?.&lt;/p&gt;
&lt;img alt="" src="https://copyninja.in/images/html_weirdness.gif" /&gt;
&lt;p&gt;I made following observation from above experiments.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;When I open original file in browser or my sample file with
&lt;cite&gt;encoding=&amp;quot;UTF-16&amp;quot;&lt;/cite&gt; its normal, no Chinese characters.&lt;/li&gt;
&lt;li&gt;When I attach the mail and send it out the attachment some how gets converted
into HTML file with Chinese characters and viewing source from browser shows
header containing xml declarations and original &lt;cite&gt;&amp;lt;html&amp;gt;&lt;/cite&gt; declarations get
ripped off and new tags show up which I've pasted below.&lt;/li&gt;
&lt;li&gt;If I download the same file and open in editor only Chinese characters are
present and no HTML tags inside it. So definitely the new tags which I saw by
viewing source in browser is added by Firefox.&lt;/li&gt;
&lt;li&gt;I create similar HTML file and change encoding I can see the characters
changing back and forth in emacs &lt;em&gt;web-mode&lt;/em&gt; when I change encoding of the
file.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01 Transitional//EN&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;META&lt;/span&gt; &lt;span class="na"&gt;http-equiv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/html; charset=utf-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So if I'm understanding this correctly, &lt;em&gt;Emacs&lt;/em&gt; due to encoding declaration
interprets the actual contents differently. To see how &lt;em&gt;Emacs&lt;/em&gt; really
interpreted the content I opened the sent mail I had in raw format and saw
following header lines for attachment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;text/html&lt;/span&gt;&lt;span class="c1"&gt;; charset=utf-8&lt;/span&gt;
&lt;span class="na"&gt;Content-Disposition&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;attachment&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;SOA-102012059675-FEBRUARY-2017.html&lt;/span&gt;
&lt;span class="na"&gt;Content-Transfer-Encoding&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base64&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This was followed with base64 encoded data. So does this mean emacs interpreted
the content as UTF-16 and encoded the content using UTF-8?. Again I've no clue,
so I changed the &lt;cite&gt;encoding&lt;/cite&gt; in both the files to be as UTF-8 and sent the mail
by attaching these files again to see what happens. And my guess was right I
could get the attachment as is on the receiving side. And inspecting raw mail
the attachment headers now different than before.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;text/html&lt;/span&gt;
&lt;span class="na"&gt;Content-Disposition&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;attachment&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;SOA-102012059675-DECEMBER-2016.html&lt;/span&gt;
&lt;span class="na"&gt;Content-Transfer-Encoding&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;quoted-printable&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See how &lt;em&gt;Content-Type&lt;/em&gt; its different now also see the
&lt;em&gt;Content-Transfer-Encoding&lt;/em&gt; its now &lt;cite&gt;quoted-printable&lt;/cite&gt; as opposed to &lt;cite&gt;base64&lt;/cite&gt;
earlier. Additionally I can see HTML content below the header.
When I opened the attachment from mail I get the actual bill.&lt;/p&gt;
&lt;p&gt;As far as I understand base64 encoding is used when the data to be attached is
base64. So I guess basically due to wrong encoding declared inside the file
&lt;em&gt;Emacs&lt;/em&gt; interpreted the content as a binary data and encoded it differently than
what it really should be. Phew that was a lot of investigation to understand the
magic but it was worth it.&lt;/p&gt;
&lt;p&gt;Do let me know your thoughts on this.&lt;/p&gt;
</content><category term="misc"/><category term="html"/><category term="encoding"/></entry><entry><title>Switching from approx to apt-cacher-ng</title><link href="https://copyninja.in/blog/approx_to_acng.html" rel="alternate"/><published>2016-07-17T16:30:00+05:30</published><updated>2016-07-17T16:30:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2016-07-17:/blog/approx_to_acng.html</id><summary type="html">&lt;p class="first last"&gt;Brief notes on my switch from approx to apt-cacher-ng&lt;/p&gt;
</summary><content type="html">&lt;p&gt;After a long ~5 years (from 2011) journey with approx I finally wanted
to switch to something new like apt-cacher-ng. And after a bit of
changes I finally managed to get apt-cacher-ng into my work flow.&lt;/p&gt;
&lt;div class="section" id="bit-of-history"&gt;
&lt;h2&gt;Bit of History&lt;/h2&gt;
&lt;p&gt;I should first give you a brief on how I started using approx. It all
started in MiniDebconf 2011 which I organized at my Alma-mater. I met
Jonas Smedegaard here and from him I learned about approx. Jonas has a
bunch of machines at his home and he was active user of approx and he
showed it to me while explaining the &lt;em&gt;Boxer&lt;/em&gt; project. I was quite
impressed with approx. Back then I was using a 230kbps slow INTERNET
connection and I was also maintaining a couple of packages in
Debian. Updating the pbuilder chroots was time consuming task for me
as I had to download multiple times over slow net. And approx largely
solved this problem and I started using it.&lt;/p&gt;
&lt;p&gt;5 years fast forward I now have quite fast INTERNET with good
FUP. (About 50GB a month), but I still tend to use approx which makes
building packages quite faster. I also use couple of containers on my
laptop which all use my laptop as approx cache.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="why-switch"&gt;
&lt;h2&gt;Why switch?&lt;/h2&gt;
&lt;p&gt;So why change to apt-cacher-ng?. Approx is a simple tool, it runs
mainly with inetd and sits between apt and the repository on
INTERNET. Where as apt-cacher-ng provides a lot of features. Below are
some listed from the apt-cacher-ng manual.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;use of TLS/SSL repositories (may be possible with approx but I'm notsure how to do it)&lt;/li&gt;
&lt;li&gt;Access control of who can access caching server&lt;/li&gt;
&lt;li&gt;Integration with debdelta (I've not tried, approx also supports
debdelta)&lt;/li&gt;
&lt;li&gt;Avoiding use of apt-cacher-ng for some hosts&lt;/li&gt;
&lt;li&gt;Avoiding caching of some file types&lt;/li&gt;
&lt;li&gt;Partial mirroring for offline usage.&lt;/li&gt;
&lt;li&gt;Selection of ipv4 or ipv6 for connections.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The biggest change I see is the speed difference between approx and
apt-cacher-ng. I think this is mainly because apt-cacher-ng is threaded where as approx
runs using inetd.&lt;/p&gt;
&lt;p&gt;I do not want all features of apt-cacher-ng at the moment, but who knows in
future I might need some features and hence I decided to switch to
apt-cacher-ng over approx.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="transition"&gt;
&lt;h2&gt;Transition&lt;/h2&gt;
&lt;p&gt;Transition from approx to apt-cacher-ng was smoother than I
expected. There are 2 approaches you can use one is explicit routing
another is transparent routing. I prefer transparent routing and I
only had to change my /etc/apt/sources.list to use the actual
repository URL.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;deb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://deb.debian.org/debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;unstable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;non-free&lt;/span&gt;
&lt;span class="k"&gt;deb-src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://deb.debian.org/debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;unstable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;deb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://deb.debian.org/debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;experimental&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;non-free&lt;/span&gt;
&lt;span class="k"&gt;deb-src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://deb.debian.org/debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;experimental&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;main&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After above change I had to add a &lt;em&gt;01proxy&lt;/em&gt; configuration file to
&lt;em&gt;/etc/apt/apt.conf.d/&lt;/em&gt; with following content.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Acquire::http::Proxy &amp;quot;http://localhost:3142/&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I use explicit routing only when using apt-cacher-ng with pbuilder and
debootstrap. Following snippet shows explicit routing through &lt;em&gt;/etc/apt/sources.list&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;deb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://localhost:3142/deb.debian.org/debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;unstable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;main&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="usage-with-pbuilder-and-friends"&gt;
&lt;h3&gt;Usage with pbuilder and friends&lt;/h3&gt;
&lt;p&gt;To use apt-cacher-ng with pbuilder you need to modify /etc/pbuilderrc
to contain following line&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;MIRRORSITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:3142/deb.debian.org/debian
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="usage-with-debootstrap"&gt;
&lt;h3&gt;Usage with debootstrap&lt;/h3&gt;
&lt;p&gt;To use apt-cacher-ng with debootstrap, pass MIRROR argument of
debootstrap as &lt;cite&gt;http://localhost:3142/deb.debian.org/debian&lt;/cite&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I've now completed full transition of my work flow to apt-cacher-ng
and purged approx and its cache.&lt;/p&gt;
&lt;div class="strike docutils container"&gt;
Though it works fine I feel that there will be 2 caches created when
you use transparent and explicit proxy using localhost:3142 URL. I'm
sure it is possible to configure this to avoid duplication, but I've
not yet figured it. If you know how to fix this do let me know.&lt;/div&gt;
&lt;div class="section" id="update"&gt;
&lt;h3&gt;Update&lt;/h3&gt;
&lt;p&gt;Jonas told me that its not 2 caches but 2 routing paths, one for
transparent routing and another for explicit routing. So I guess there
is nothing here to fix :-).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="apt"/><category term="approx"/><category term="apt-cacher-ng"/><category term="debian"/></entry><entry><title>Integrating Cython extension with setuptools and unit testing</title><link href="https://copyninja.in/blog/cython_setuptools.html" rel="alternate"/><published>2016-06-26T19:54:00+05:30</published><updated>2016-06-26T19:54:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2016-06-26:/blog/cython_setuptools.html</id><summary type="html">&lt;p class="first last"&gt;This post describes how to integrate a cython extension with
setuptools.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I was reviewing changes for &lt;a class="reference external" href="https://github.com/libindic/indic-trans"&gt;indic-trans&lt;/a&gt; as part of GSoC 2016. The
module is an improvisation for our original transliteration module
which was doing its job by substitution.&lt;/p&gt;
&lt;p&gt;This new module uses machine learning of some sort and utilizes
&lt;em&gt;Cython&lt;/em&gt;, &lt;em&gt;numpy&lt;/em&gt; and &lt;em&gt;scipy&lt;/em&gt;. Student had kept pre-compiled shared
library in the git tree to make sure it builds and passes the
test. But this was not correct way. I started looking at way to build
these files and remove it from the code base.&lt;/p&gt;
&lt;p&gt;There is a &lt;a class="reference external" href="http://docs.cython.org/src/quickstart/build.html"&gt;cython documentation&lt;/a&gt; for distutils but
none for setuptools. Probably it is similar to other Python extension
integration into setuptools, but this was first time for me so after a
bit of searching and trial and error below is what I did.&lt;/p&gt;
&lt;p&gt;We need to use &lt;cite&gt;Extensions&lt;/cite&gt; class from setuptools and give it path to
modules we want to build. In my case &lt;cite&gt;beamsearch&lt;/cite&gt; and &lt;cite&gt;viterbi&lt;/cite&gt; are 2
modules. So I added following lines to setup.py&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;setuptools.extension&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Extension&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;Cython.Build&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cythonize&lt;/span&gt;

&lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
 &lt;span class="n"&gt;Extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="s2"&gt;&amp;quot;indictrans._decode.beamsearch&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;[&lt;/span&gt;
         &lt;span class="s2"&gt;&amp;quot;indictrans/_decode/beamsearch.pyx&amp;quot;&lt;/span&gt;
     &lt;span class="p"&gt;],&lt;/span&gt;
     &lt;span class="n"&gt;include_dirs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_include&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
 &lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="n"&gt;Extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="s2"&gt;&amp;quot;indictrans._decode.viterbi&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;[&lt;/span&gt;
         &lt;span class="s2"&gt;&amp;quot;indictrans/_decode/viterbi.pyx&amp;quot;&lt;/span&gt;
     &lt;span class="p"&gt;],&lt;/span&gt;
     &lt;span class="n"&gt;include_dirs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_include&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First argument to &lt;cite&gt;Extensions&lt;/cite&gt; is the module name and second argument
is a list of files to be used in building the module. The additional
&lt;cite&gt;inculde_dirs&lt;/cite&gt; argument is not normally necessary unless you are
working in virtualenv. In my system the build used to work without
this but it was failing in Travis CI, so added it to fix the CI
builds. OTOH it did work without this on Circle CI.&lt;/p&gt;
&lt;p&gt;Next is provide this &lt;cite&gt;extensions&lt;/cite&gt; to &lt;cite&gt;ext_modules&lt;/cite&gt; argument to &lt;cite&gt;setup&lt;/cite&gt;
as shown below&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="n"&gt;setup_requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pbr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="n"&gt;pbr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;ext_modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cythonize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And for the reference here is full setup.py after modifications.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;setuptools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;setuptools.extension&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Extension&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;Cython.Build&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cythonize&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt;


&lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="n"&gt;Extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="s2"&gt;&amp;quot;indictrans._decode.beamsearch&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;[&lt;/span&gt;
         &lt;span class="s2"&gt;&amp;quot;indictrans/_decode/beamsearch.pyx&amp;quot;&lt;/span&gt;
     &lt;span class="p"&gt;],&lt;/span&gt;
     &lt;span class="n"&gt;include_dirs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_include&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;Extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="s2"&gt;&amp;quot;indictrans._decode.viterbi&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;[&lt;/span&gt;
         &lt;span class="s2"&gt;&amp;quot;indictrans/_decode/viterbi.pyx&amp;quot;&lt;/span&gt;
     &lt;span class="p"&gt;],&lt;/span&gt;
     &lt;span class="n"&gt;include_dirs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_include&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;setup_requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pbr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="n"&gt;pbr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;ext_modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cythonize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So now we can build the extensions (shared library) using following
command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;setup.py&lt;span class="w"&gt; &lt;/span&gt;build_ext
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Another challenge I faced was missing extension when running test. We
use pbr in above project and testrepository with subunit for running
tests. Looks like it does not build extensions by default so I
modified the Makefile to build the extension in place before running
test. The &lt;cite&gt;travis&lt;/cite&gt; target of my Makefile is as follows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nf"&gt;travis&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;.testrepository&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;.testrepository&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;times.dbm*&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-delete
&lt;span class="w"&gt;     &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;setup.py&lt;span class="w"&gt; &lt;/span&gt;build_ext&lt;span class="w"&gt; &lt;/span&gt;-i
&lt;span class="w"&gt;     &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;setup.py&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--coverage&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;--coverage-package-name&lt;span class="o"&gt;=&lt;/span&gt;indictrans
&lt;span class="w"&gt;     &lt;/span&gt;flake8&lt;span class="w"&gt; &lt;/span&gt;--max-complexity&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;indictrans
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I had to build the extension in place using &lt;cite&gt;-i&lt;/cite&gt; switch. This is
because other wise the tests won't find the
&lt;cite&gt;indictrans._decode.beamsearch&lt;/cite&gt; and &lt;cite&gt;indictrans._decode.viterbi
modules&lt;/cite&gt;. What basically &lt;cite&gt;-i&lt;/cite&gt; switch does is after building shared
library symlinks it to the module directory, in ourcase
&lt;cite&gt;indictrans._decode&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;The test for existence of .testrepository folder is over come &lt;a class="reference external" href="https://bugs.launchpad.net/testrepository/+bug/1229445"&gt;this
bug&lt;/a&gt; in
testrepository which results in test failure when running tests using
&lt;cite&gt;tox&lt;/cite&gt;.&lt;/p&gt;
</content><category term="development"/><category term="python"/><category term="cython"/><category term="setuptools"/><category term="pbr"/></entry><entry><title>Managing Virtual Network Devices with systemd-networkd</title><link href="https://copyninja.in/blog/systemd-networkd-networking.html" rel="alternate"/><published>2016-01-10T22:26:00+05:30</published><updated>2016-01-10T22:26:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2016-01-10:/blog/systemd-networkd-networking.html</id><summary type="html">&lt;p class="first last"&gt;Using systemd-networkd to manage virtual network devices in
Linux&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I've been using bridge networking and tap networking for containers
and virtual machines on my system. Configuration for bridge network
which I use to connect containers was configured using
&lt;em&gt;/etc/network/interfaces&lt;/em&gt; file as shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;auto natbr0
iface natbr0 inet static
   address 172.16.10.1
   netmask 255.255.255.0
   pre-up brctl addbr natbr0
   post-down brctl delbr natbr0
   post-down sysctl net.ipv4.ip_forward=0
   post-down sysctl net.ipv6.conf.all.forwarding=0
   post-up sysctl net.ipv4.ip_forward=1
   post-up sysctl net.ipv6.conf.all.forwarding=1
   post-up iptables -A POSTROUTING -t mangle -p udp --dport bootpc -s 172.16.0.0/16 -j CHECKSUM --checksum-fill
   pre-down iptables -D POSTROUTING -t mangle -p udp --dport bootpc -s 172.16.0.0/16 -j CHECKSUM --checksum-fill
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Basically I setup masquerading and IP forwarding when network comes up
using this, so all my containers and virtual machines can access
internet.&lt;/p&gt;
&lt;p&gt;This can be simply done using systemd-networkd with couple of lines,
yes couple of lines. For this to work first you need to enable
systemd-networkd.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemd-networkd.service
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now I need to write 2 configuration file for the above bridge
interface under &lt;em&gt;/etc/systemd/network&lt;/em&gt;. One file is &lt;em&gt;natbr0.netdev&lt;/em&gt;
which configures the bridge and the &lt;em&gt;natbr0.network&lt;/em&gt; which configures
IP address and other stuff for the bridge interface.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;#natbr0.netdev&lt;/span&gt;
&lt;span class="k"&gt;[NetDev]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Bridge interface for containers/vms&lt;/span&gt;
&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;natbr0&lt;/span&gt;
&lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;#natbr0.network&lt;/span&gt;
&lt;span class="k"&gt;[Match]&lt;/span&gt;
&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;natbr0&lt;/span&gt;

&lt;span class="k"&gt;[Network]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;IP configuration for natbr0&lt;/span&gt;
&lt;span class="na"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;172.16.10.1/16&lt;/span&gt;
&lt;span class="na"&gt;IPForward&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;IPMasquerade&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;em&gt;IPForward&lt;/em&gt; in above configuration is actually redundant, when I
set &lt;em&gt;IPMasquerade&lt;/em&gt; it automatically enables IPForward. So these
configuration is equivalent of what I did in my &lt;em&gt;interfaces&lt;/em&gt; file. It
also avoids me doing additional &lt;em&gt;iptables&lt;/em&gt; usage to add masquerading
rules. This pretty much simplifies handling of virtual network
devices.&lt;/p&gt;
&lt;p&gt;There are many other things which can you do with systemd-networkd,
like running a DHCPServer on the interface and many other things. I
suggest you to read manual pages on &lt;em&gt;systemd.network(5)&lt;/em&gt; and
&lt;em&gt;systemd.netdev(5)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;systemd-networkd allows you configure all type of virtual networking
devices and actual network interfaces. I've not myself used it to
handle actual network interfaces yet.&lt;/p&gt;
</content><category term="devops"/><category term="systemd-networkd"/><category term="systemd"/><category term="networking"/></entry><entry><title>Persisting resource control options for systemd-nspawn containers</title><link href="https://copyninja.in/blog/persist_resource_control.html" rel="alternate"/><published>2015-12-15T20:30:00+05:30</published><updated>2015-12-15T20:30:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2015-12-15:/blog/persist_resource_control.html</id><summary type="html">&lt;p class="first last"&gt;Steps to persist the resource control options for
systemd-nspawn containers.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In my previous &lt;a class="reference external" href="https://copyninja.info/blog/taming_systemd_nsapwn.html"&gt;post on systemd-nspawn&lt;/a&gt; I
mentioned, I was unclear on how to persist resource control options
for a container.  Today I accidentally discovered how can the property
be persisted across boot without modifying service file or writing
custom service file for container. It is done using &lt;em&gt;systemctl
set-property&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To set &lt;em&gt;CPUAccounting&lt;/em&gt; and &lt;em&gt;CPUShares&lt;/em&gt; for a container we need to run
following command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;set-property&lt;span class="w"&gt; &lt;/span&gt;systemd-nspawn@container.service&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;CPUACCounting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CPUShares&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This actually persists these settings at location,
&lt;em&gt;/etc/systemd/systemd-nspawn&amp;#64;container.service.d/&lt;/em&gt; folder. So in our
case there will be 2 files created under above location by name
&lt;em&gt;50-CPUAccounting.conf&lt;/em&gt; and &lt;em&gt;50-CPUShares.conf&lt;/em&gt; with following
contents.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# 50-CPUAccounting.conf&lt;/span&gt;
&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;CPUAccounting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;

&lt;span class="c1"&gt;# 50-CPUShares.conf&lt;/span&gt;
&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;CPUShares&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;200&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Today when I discovered this folder and saw the file contents, I
became curious and started to wonder who created this folder. The look
at systemctl man page made showed me this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;set-property NAME ASSIGNMENT...&lt;/dt&gt;
&lt;dd&gt;&lt;p class="first"&gt;Set the specified unit properties at runtime where this is
supported. This allows changing configuration parameter
properties such as resource control settings at
runtime. Not all properties may be changed at runtime, but
many resource control settings (primarily those in
systemd.resource-control(5)) may. The changes are applied
instantly, and stored on disk for future boots,
unless --runtime is passed, in which case the settings only
apply until the next reboot. The syntax of the property
assignment follows closely the syntax of assignments in
unit files.&lt;/p&gt;
&lt;p&gt;Example: systemctl set-property foobar.service CPUShares=777&lt;/p&gt;
&lt;p class="last"&gt;Note that this command allows changing multiple properties
at the same time, which is preferable over setting them
individually. Like unit file configuration settings,
assigning the empty list to list parameters will reset the
list.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/blockquote&gt;
&lt;p&gt;I did remember doing this for my container and hence it became clear
these files are actually written by &lt;em&gt;systemctl set-property&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In case you don't want to persist the properties across boot you can
simply pass &lt;em&gt;--runtime&lt;/em&gt; switch.&lt;/p&gt;
&lt;p&gt;Basically this is not just for container, resource control can be thus
applied to any running service on the system. This is actually cool.&lt;/p&gt;
</content><category term="devops"/><category term="systemd"/><category term="systemd-nspawn"/><category term="resource-control"/><category term="containers"/></entry><entry><title>Ordering mount points in Jessie (systemd &lt; 220)</title><link href="https://copyninja.in/blog/ordering_mount_in_jessie.html" rel="alternate"/><published>2015-12-14T22:26:00+05:30</published><updated>2015-12-14T22:26:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2015-12-14:/blog/ordering_mount_in_jessie.html</id><summary type="html">&lt;p class="first last"&gt;Describes on how to achieve mount ordering in Jessie where
x-systemd.requires is not present.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In the previous &lt;a class="reference external" href="https://copyninja.info/blog/systemd_automount_entry.html"&gt;post&lt;/a&gt; I had
mentioned that I didn't figure out how to add dependency on mount
points so as to achieve correct ordering of mount points. After a lot
of search today I finally figured it out thanks to the &lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=812826"&gt;bug report&lt;/a&gt; and the &lt;a class="reference external" href="http://lists.freedesktop.org/archives/systemd-devel/2015-May/031932.html"&gt;patch&lt;/a&gt;
which adds &lt;em&gt;x-systemd.requires&lt;/em&gt; and other option to systemd.&lt;/p&gt;
&lt;p&gt;So basically you can add additional ordering information to the
&lt;em&gt;.mount&lt;/em&gt; files generated by &lt;em&gt;systemd-fstab-generator&lt;/em&gt; by adding a
&lt;em&gt;ordering.conf&lt;/em&gt; file to path
&lt;em&gt;/etc/systemd/system/usr-local-bin.mount.d/&lt;/em&gt; path with following
contents.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;home.mount&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that is it, now &lt;em&gt;usr-local-bin.mount&lt;/em&gt; will be mounted after
&lt;em&gt;home.mount&lt;/em&gt; is activated.&lt;/p&gt;
&lt;p&gt;I couldn't find this information directly in related manpages like
&lt;em&gt;systemd.mount&lt;/em&gt; or &lt;em&gt;systemd.automount&lt;/em&gt;. Also this information is not
directly available in search results!.&lt;/p&gt;
</content><category term="devops"/><category term="debian"/><category term="systemd"/><category term="mount"/><category term="fstab"/></entry><entry><title>Mount ordering and automount options in systemd</title><link href="https://copyninja.in/blog/systemd_automount_entry.html" rel="alternate"/><published>2015-12-13T15:13:00+05:30</published><updated>2015-12-13T15:13:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2015-12-13:/blog/systemd_automount_entry.html</id><summary type="html">&lt;p class="first last"&gt;Brief notes on systemd.mount and systemd.autmount features.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Just to give a brief recap of why I'm writing this post, I've to
describe a brief encounter I had with systemd which rendered my system
unbootable. I first felt its systemd's problem but later figured out
it was my mistake. So below is brief story divided into 2 sections
&lt;em&gt;Problem&lt;/em&gt; and &lt;em&gt;Solution&lt;/em&gt;. Here &lt;em&gt;Problem&lt;/em&gt; describes issue I faced with
systemd and &lt;em&gt;Solution&lt;/em&gt; discusses the &lt;em&gt;.mount&lt;/em&gt; and &lt;em&gt;.automount&lt;/em&gt; suffix
files used by systemd.&lt;/p&gt;
&lt;div class="section" id="problem"&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;I have several local bin folders and I don't want to modify &lt;em&gt;PATH&lt;/em&gt;
environment variable adding every other folder path. I first started
using &lt;em&gt;aufs&lt;/em&gt; as alternative to symlinks or modifying &lt;em&gt;PATH&lt;/em&gt;
variable. Recently I learnt about much more light weight union fs which is
in kernel, &lt;em&gt;overlayfs&lt;/em&gt;. And Google led me to Arch wiki article which
showed me a fstab entry like below&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;overlay        /usr/local/bin        overlay noauto,x-systemd.automount,lowerdir=/home/vasudev/Documents/utilities/bin,upperdir=/home/vasudev/Documents/utilities/jonas-bin,workdir=/home/vasudev/Documents/utilities/bin-overlay    0       0
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And after adding this entry, on next reboot systemd is not able to
mount my LVM home and swap partition. It does however mount root
partition. It gives me emergency target but login never returns. So
without any alternative I had to reinstall the system. But funnily
enough I started encountering the same issue (yeah after I had added
above entry into fstab). Yeah that time I never thought that its
culprit. My friend Ritesh finally got my system booting after the
weird x-systemd.automount option. I never investigated further that
time on why this problem occurred.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="solution"&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;After re-encounter with similar problem and some other project I read
the manual on &lt;em&gt;systemd.mount&lt;/em&gt;, &lt;em&gt;systemd-fstab-generator&lt;/em&gt; and
&lt;em&gt;systemd.automount&lt;/em&gt; and I had some understanding of what really went
wrong in my case above.&lt;/p&gt;
&lt;p&gt;So now let us see what really is happening. All the above happened
because, &lt;em&gt;systemd translates the /etc/fstab into .mount units at run
time using systemd-fstab-generator&lt;/em&gt;. Every entry in fstab translates
into a file named after the mount point. The &lt;em&gt;/&lt;/em&gt; in the path of the
mount point is replaced by a &lt;em&gt;-&lt;/em&gt;. So &lt;em&gt;/&lt;/em&gt; mount point is named as
&lt;em&gt;-.mount&lt;/em&gt; and &lt;em&gt;/home&lt;/em&gt; is named as &lt;em&gt;home.mount&lt;/em&gt; and &lt;em&gt;/boot&lt;/em&gt; becomes
&lt;em&gt;boot.mount&lt;/em&gt;. All these files can be seen in directory
&lt;em&gt;/run/systemd/generator&lt;/em&gt;. And all these mount points are needed by
&lt;em&gt;local-fs.target&lt;/em&gt; , if any of these mount points fail,
&lt;em&gt;local-fs.target&lt;/em&gt; fails. And if &lt;em&gt;local-fs.target&lt;/em&gt; fails it will invoke
&lt;em&gt;emergency.target&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;systemd-fstab-generator&lt;/em&gt; manual suggests the ordering information in
&lt;em&gt;/etc/fstab&lt;/em&gt; is discarded. That means if you have union mounts, bind
mounts or fuse mounts in the fstab which is normally at end of fstab
and uses path from /home or some other device mount points it will
fail to get mounted. This happens because &lt;em&gt;systemd-fstab-generator&lt;/em&gt;
didn't  consider the ordering in fstab. This is what happened in my
case my &lt;em&gt;overlay&lt;/em&gt; mount point which is &lt;em&gt;usr-local-bin.mount&lt;/em&gt; was some
how happened to be tried before &lt;em&gt;home.mount&lt;/em&gt; because there is no
explicit dependency like &lt;em&gt;Requires=&lt;/em&gt; or &lt;em&gt;After=&lt;/em&gt; was declared. When
systemd tried to mount it the path required under /home were not
really present hence failed which in return invoked &lt;em&gt;emergency.target&lt;/em&gt;
as &lt;em&gt;usr-local-bin.mount&lt;/em&gt; is &lt;em&gt;Requires=&lt;/em&gt; dependency for
&lt;em&gt;local-fs.target&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Now what I didn't understand is why &lt;em&gt;emregency.target&lt;/em&gt; never gave me
the root shell after entering login information. I feel that this part
is unrelated to the problem I described above and is some other bug.&lt;/p&gt;
&lt;p&gt;To over come this what we can do is provided &lt;em&gt;systemd-fstab-generator&lt;/em&gt;
some information on dependency of each mount point. &lt;em&gt;systemd.mount&lt;/em&gt;
manual page suggests several such options. One which I used in my case
is &lt;em&gt;x-systemd.requires&lt;/em&gt; which should be placed in options column of
fstab and specify the mount point which is needed before it has to be
mounted. So my overlay fs entry translates to something like below&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;overlay        /usr/local/bin        overlay noauto,x-systemd.requires=/home,x-systemd.automount,lowerdir=/home/vasudev/Documents/utilities/bin,upperdir=/home/vasudev/Documents/utilities/jonas-bin,workdir=/home/vasudev/Documents/utilities/bin-overlay   0       0
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is another special option called &lt;em&gt;x-systemd.automount&lt;/em&gt; this will
make systemd-fstab-generator to create a &lt;em&gt;.automount&lt;/em&gt; file for this
mount point. What does &lt;em&gt;systemd.automount&lt;/em&gt; do? It achieves on-demand
file mounting and parallelized file system mounting. Something similar
to &lt;em&gt;systemd.socket&lt;/em&gt; the file system will be mounted when you access
the mount point for first time.&lt;/p&gt;
&lt;p&gt;So now if you try to see dependency of usr-local-bin.mount you will
see following.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;After&lt;span class="w"&gt; &lt;/span&gt;usr-local-bin.mount
&lt;span class="nv"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-.mount&lt;span class="w"&gt; &lt;/span&gt;systemd-journald.socket&lt;span class="w"&gt; &lt;/span&gt;local-fs-pre.target&lt;span class="w"&gt; &lt;/span&gt;system.slice&lt;span class="w"&gt; &lt;/span&gt;usr-local-bin.automount
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This means now &lt;em&gt;usr-local-bin.mount&lt;/em&gt; depends on
&lt;em&gt;usr-local-bin.automount&lt;/em&gt;. And let us see what usr-local-bin.automount
needs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;Requires&lt;span class="w"&gt; &lt;/span&gt;usr-local-bin.automount
&lt;span class="nv"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-.mount&lt;span class="w"&gt; &lt;/span&gt;home.mount

systemctl&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;After&lt;span class="w"&gt; &lt;/span&gt;usr-local-bin.automount
&lt;span class="nv"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-.mount&lt;span class="w"&gt; &lt;/span&gt;home.mount
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So clearly &lt;em&gt;usr-local-bin.automount&lt;/em&gt; is activated after &lt;em&gt;-.mount&lt;/em&gt; and
&lt;em&gt;home.mount&lt;/em&gt; is activated. Similar can be done for any bind mounts or
fuse mounts which require other mount points before it can be
mounted. Also note that &lt;em&gt;x-systemd.autmount&lt;/em&gt; is not mandatory option
for declaring dependencies, I used it just to make sure
&lt;em&gt;/usr/local/bin&lt;/em&gt; is mounted only when its really needed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;A lot of traditional way has been changed by systemd. I never
understood why my system failed to boot in first place this happened
because I was not really aware of how systemd works and was trying to
debug the problem with traditional approach. So there is really a
learning curve involved for every sysadmin out there who is going to
use systemd. Most of them will read documentation before hand but
others like me will learn after having a situation like above. :-).&lt;/p&gt;
&lt;p&gt;So systemd interfering into /etc/fstab is good?. I don't know but
since systemd parallelizes  the boot procedure something like this is
really needed. Is there a way to make systemd not touch
/etc/fstab?. Yes there is you need to pass &lt;em&gt;fstab=0&lt;/em&gt; option in kernel
command line and systemd-fstab-generator doesn't create any .mount or
.swap files from your /etc/fstab.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;!NB Also it looks like x-systemd.requires option was introduced
recently and is not available in systemd &amp;lt;= 215 which is default in
Jessie. So how do you declare dependencies in Jessie system?. I don't
have any answer!. I did read that x-systemd.automount which is
available in those versions of systemd can be used, but I'm yet to
experiment this. If it succeeds I will write a post on it.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="systemd"/><category term="fstab"/><category term="automount"/></entry><entry><title>Forwarding host port to service in container</title><link href="https://copyninja.in/blog/port_forward_container.html" rel="alternate"/><published>2015-11-09T17:06:00+05:30</published><updated>2015-11-09T17:06:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2015-11-09:/blog/port_forward_container.html</id><summary type="html">&lt;p class="first last"&gt;Brief notes on forwarding specific ports to service running
in container.&lt;/p&gt;
</summary><content type="html">&lt;div class="section" id="problem"&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;I've lxc container running distcc daemon and I would like to forward
the distcc traffic coming to my host system to container.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="solution"&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;Following simple script which uses iptable did the job.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e


usage&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="s"&gt;    $(basename $0) [options] &amp;lt;in-interface&amp;gt; &amp;lt;out-interface&amp;gt; &amp;lt;port&amp;gt; &amp;lt;destination&amp;gt;&lt;/span&gt;

&lt;span class="s"&gt;    --clear           Clear the previous rules before inserting new&lt;/span&gt;
&lt;span class="s"&gt;                      ones&lt;/span&gt;

&lt;span class="s"&gt;    --protocol        Protocol for the rules to use.&lt;/span&gt;

&lt;span class="s"&gt;    in-interface      Interface on which incoming traffic is expected&lt;/span&gt;
&lt;span class="s"&gt;    out-interface     Interface to which incoming traffic is to be&lt;/span&gt;
&lt;span class="s"&gt;                      forwarded.&lt;/span&gt;

&lt;span class="s"&gt;    port              Port to be forwarded. Can be integer or string&lt;/span&gt;
&lt;span class="s"&gt;                      from /etc/services.&lt;/span&gt;
&lt;span class="s"&gt;    destination       IP and port of the destination system to which&lt;/span&gt;
&lt;span class="s"&gt;                      traffic needs to be forwarded. This should be in&lt;/span&gt;
&lt;span class="s"&gt;                      form &amp;lt;destination_ip:port&amp;gt;&lt;/span&gt;

&lt;span class="s"&gt;(C) 2015 Vasudev Kamath - This program comes with ABSOLUTELY NO&lt;/span&gt;
&lt;span class="s"&gt;WARRANTY. This is free software, and you are welcome to redistribute&lt;/span&gt;
&lt;span class="s"&gt;it under the GNU GPL Version 3 (or later) License&lt;/span&gt;

&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

setup_portforwarding&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;PREROUTING&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$IN_INTERFACE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$protocol&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--dport&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$PORT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;DNAT&lt;span class="w"&gt; &lt;/span&gt;--to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DESTINATION&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$protocol&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DESTINATION&lt;/span&gt;&lt;span class="p"&gt;%%&lt;/span&gt;&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--dport&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$PORT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Returning packet should have gateway IP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;POSTROUTING&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DESTINATION&lt;/span&gt;&lt;span class="p"&gt;%%&lt;/span&gt;&lt;span class="se"&gt;\:&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="nv"&gt;$IN_INTERFACE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;SNAT&lt;span class="w"&gt; &lt;/span&gt;--to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IN_IP&lt;/span&gt;&lt;span class="p"&gt;%%&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You need to be root to run this script&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;true&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;--clear&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nv"&gt;CLEAR_RULES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;--protocol&lt;span class="p"&gt;|&lt;/span&gt;--protocol&lt;span class="o"&gt;=&lt;/span&gt;*?&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--protocol&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nv"&gt;PROTOCOL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#--protocol=&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nv"&gt;PROTOCOL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1$-&lt;/span&gt;&lt;span class="p"&gt;-protocol=&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You need to specify protocl (tcp|udp)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;*&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;usage&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nv"&gt;IN_INTERFACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;OUT_INTERFACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;DESTINATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Get the incoming interface IP. This is used for SNAT.&lt;/span&gt;
&lt;span class="nv"&gt;IN_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;addr&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$IN_INTERFACE&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;perl&lt;span class="w"&gt; &lt;/span&gt;-nE&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/inet\s(.*)\sbrd/ and print $1&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$CLEAR_RULES&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;-X
&lt;span class="w"&gt;    &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;-F
&lt;span class="w"&gt;    &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-F
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PROTOCOL&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;setup_portforwarding&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$PROTOCOL&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;setup_portforwarding&lt;span class="w"&gt; &lt;/span&gt;tcp
&lt;span class="w"&gt;    &lt;/span&gt;setup_portforwarding&lt;span class="w"&gt; &lt;/span&gt;udp
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Coming to systemd-nspawn I see there is &lt;em&gt;--port&lt;/em&gt; option which takes
argument in form &lt;em&gt;proto:hostport:destport&lt;/em&gt; where proto can be either
&lt;em&gt;tcp&lt;/em&gt; or &lt;em&gt;udp&lt;/em&gt;, &lt;em&gt;hostport&lt;/em&gt; and &lt;em&gt;destport&lt;/em&gt; are number from
1-65535. This option assumes private networking enabled in the
container. I've not tried this option yet but that simplifies quite a
lot of thing, its like -p switch used by &lt;em&gt;docker&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="iptables"/><category term="firewall"/><category term="container"/></entry><entry><title>Taming systemd-nspawn for running containers</title><link href="https://copyninja.in/blog/taming_systemd_nsapwn.html" rel="alternate"/><published>2015-11-09T12:52:00+05:30</published><updated>2015-11-09T12:52:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2015-11-09:/blog/taming_systemd_nsapwn.html</id><summary type="html">&lt;p class="first last"&gt;Brief notes on maintaining container using systemd-nspawn&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I've been trying to run containers using systemd-nspawn for quite some
time. I was always bumping to one or other dead end. This is not
systemd-nspawn's fault, rather my impatience stopping me from reading
manual pages properly lack of good tutorial like article available
online. Compared to this LXC has a quite a lot of good tutorials and
howto's available online.&lt;/p&gt;
&lt;p&gt;This article is my effort to create a notes putting all required
information in one place.&lt;/p&gt;
&lt;div class="section" id="creating-a-debian-base-install"&gt;
&lt;h2&gt;Creating a Debian Base Install&lt;/h2&gt;
&lt;p&gt;First step is to have a minimal Debian system some where on your hard
disk. This can be easily done using &lt;em&gt;debootsrap&lt;/em&gt;. I wrote a custom
script to avoid reading manual every time I want to run
debootstrap. Parts of this script (mostly packages and the root
password generation) is stolen from &lt;em&gt;lxc-debian&lt;/em&gt; template provided by
lxc package.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-x

usage&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="p"&gt;##/*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; [options] &amp;lt;suite&amp;gt; &amp;lt;target&amp;gt; [&amp;lt;mirror&amp;gt;]&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bootstrap rootfs for Debian&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="s"&gt;    --arch         set the architecture to install&lt;/span&gt;
&lt;span class="s"&gt;    --root-passwd  set the root password for bootstrapped rootfs&lt;/span&gt;
&lt;span class="s"&gt;    EOF&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# copied from the lxc-debian template&lt;/span&gt;
&lt;span class="nv"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ifupdown,&lt;span class="se"&gt;\&lt;/span&gt;
locales,&lt;span class="se"&gt;\&lt;/span&gt;
libui-dialog-perl,&lt;span class="se"&gt;\&lt;/span&gt;
dialog,&lt;span class="se"&gt;\&lt;/span&gt;
isc-dhcp-client,&lt;span class="se"&gt;\&lt;/span&gt;
netbase,&lt;span class="se"&gt;\&lt;/span&gt;
net-tools,&lt;span class="se"&gt;\&lt;/span&gt;
iproute,&lt;span class="se"&gt;\&lt;/span&gt;
openssh-server,&lt;span class="se"&gt;\&lt;/span&gt;
dbus

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You must be root to execute this command&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-lt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;usage&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;true&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;--root-passwd&lt;span class="p"&gt;|&lt;/span&gt;--root-passwd&lt;span class="o"&gt;=&lt;/span&gt;?*&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--root-passwd&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;ROOT_PASSWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#--root-passwd=&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;ROOT_PASSWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#--root-passwd=&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# copied from lxc-debian template&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;ROOT_PASSWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/urandom&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;/dev/null&lt;span class="p"&gt;|&lt;/span&gt;base64&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;ECHO_PASSWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;yes&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;--arch&lt;span class="p"&gt;|&lt;/span&gt;--arch&lt;span class="o"&gt;=&lt;/span&gt;?*&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--arch&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;ARCHITECTURE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#--arch=&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;ARCHITECTURE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#--arch=&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;ARCHITECTURE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg-architecture&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;DEB_HOST_ARCH&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;*&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;



&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-z&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-z&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You must specify suite and target&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;MIRROR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nv"&gt;MIRROR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MIRROR&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;http&lt;/span&gt;&lt;span class="p"&gt;://httpredir.debian.org/debian&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Downloading Debian &lt;/span&gt;&lt;span class="nv"&gt;$release&lt;/span&gt;&lt;span class="s2"&gt; ...&amp;quot;&lt;/span&gt;
debootstrap&lt;span class="w"&gt; &lt;/span&gt;--verbose&lt;span class="w"&gt; &lt;/span&gt;--variant&lt;span class="o"&gt;=&lt;/span&gt;minbase&lt;span class="w"&gt; &lt;/span&gt;--arch&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ARCHITECTURE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;--include&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$packages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$release&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$MIRROR&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$ROOT_PASSWD&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;root:&lt;/span&gt;&lt;span class="nv"&gt;$ROOT_PASSWD&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chroot&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chpasswd
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Root password is &amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;$ROOT_PASSWRD&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;, please change!&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It just gets my needs done, if you don't like it feel free to modify
or use debootstrap directly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;!NB Please install dbus package in the minimal base install,
otherwise you will not be able to control the container using
machinectl&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="manually-running-container-and-then-persisting-it"&gt;
&lt;h2&gt;Manually Running Container and then persisting it&lt;/h2&gt;
&lt;p&gt;Next we need to run the container manually. This is done by using
following command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemd-nspawn&lt;span class="w"&gt; &lt;/span&gt;-bD&lt;span class="w"&gt;   &lt;/span&gt;/path/to/container&lt;span class="w"&gt; &lt;/span&gt;--network-veth&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;--network-bridge&lt;span class="o"&gt;=&lt;/span&gt;natbr0&lt;span class="w"&gt; &lt;/span&gt;--machine&lt;span class="o"&gt;=&lt;/span&gt;Machinename
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;--machine&lt;/em&gt; option is not mandatory, if not specified systemd-nspawn
will take the directory name as machine name, and if you have
characters like - in the directory name it translates to hexcode x2d
and controlling container with name becomes difficult.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;--network-veth&lt;/em&gt; specifies the systemd-nspawn to enable virtual
ethernet based networking and &lt;em&gt;--network-bridge&lt;/em&gt; tells the bridge
interface on host system to be used by systemd-nspawn. These options
together constitutes &lt;em&gt;private networking&lt;/em&gt; for container. If not
specified container can use host systems interface there by removing
network isolation of container.&lt;/p&gt;
&lt;p&gt;Once you run this command container comes up. You can now run
machinectl to control the container. Container can be persisted using
following command&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;machinectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;container-name
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will create a symbolic link of
&lt;em&gt;/lib/systemd/system/systemd-nspawn&amp;#64;service&lt;/em&gt; to
&lt;em&gt;/etc/systemd/system/machine.target.wants/&lt;/em&gt;. This allows you to start
or stop container using &lt;em&gt;machinectl&lt;/em&gt; or &lt;em&gt;systemctl&lt;/em&gt; command. Only
catch here is your base install should be in
&lt;em&gt;/var/lib/machines/&lt;/em&gt;. What I do in my case is create a symbolic link
from my base container to &lt;em&gt;/var/lib/machines/container-name&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;!NB Note that symbolic link name under /var/lib/machines should be
same as the container name you gave using --machine switch or the
directory name if you didn't specify --machine&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="persisting-container-networking"&gt;
&lt;h2&gt;Persisting Container Networking&lt;/h2&gt;
&lt;p&gt;We did persist the container in above step, but this doesn't persist
the networking options we provided in command
line. systemd-nspawn&amp;#64;.service provides following command to invoke
container.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth --settings=override --machine=%I&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To persist the bridge networking configuration we did in command line,
we need the help of systemd-networkd. So first we need to enable the
systemd-networkd.service on both container and the host system.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemd-networkd.service
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now inside the container, interfaces will be named as
&lt;em&gt;hostN&lt;/em&gt;. Depending on how many interfaces we have N increments. In our
example case we had single interface, hence it will named as
&lt;em&gt;host0&lt;/em&gt;. By default network interfaces will be down inside container,
hence systemd-networkd is needed to put it up.&lt;/p&gt;
&lt;p&gt;We put the following in /etc/systemd/network/host0.network file inside
the container.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Match]&lt;/span&gt;
&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;host0&lt;/span&gt;

&lt;span class="k"&gt;[Network]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Container wired interface host0&lt;/span&gt;
&lt;span class="na"&gt;DHCP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And in the host system we just configure the bridge interface using
systemd-nspawn. I put following in &lt;em&gt;natbr0.netdev&lt;/em&gt; in
/etc/systemd/network/&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[NetDev]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Bridge natbr0&lt;/span&gt;
&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;natbr0&lt;/span&gt;
&lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In my case I already had configured the bridge using
&lt;em&gt;/etc/network/interfaces&lt;/em&gt; file for lxc. I think its not really needed
to use systemd-networkd in this case. Since systemd-networkd doesn't
do anything if network / virtual device is already present I safely
put above configuration and enabled systemd-networkd.&lt;/p&gt;
&lt;p&gt;Just for the notes here is my natbr0 configuration in &lt;em&gt;interfaces&lt;/em&gt;
file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;auto natbr0
iface natbr0 inet static
   address 172.16.10.1
   netmask 255.255.255.0
   pre-up brctl addbr natbr0
   post-down brctl delbr natbr0
   post-down sysctl net.ipv4.ip_forward=0
   post-down sysctl net.ipv6.conf.all.forwarding=0
   post-up sysctl net.ipv4.ip_forward=1
   post-up sysctl net.ipv6.conf.all.forwarding=1
   post-up iptables -A POSTROUTING -t mangle -p udp --dport bootpc -s 172.16.0.0/16 -j CHECKSUM --checksum-fill
   pre-down iptables -D POSTROUTING -t mangle -p udp --dport bootpc -s 172.16.0.0/16 -j CHECKSUM --checksum-fill
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once this is done just reload the &lt;em&gt;systemd-networkd&lt;/em&gt; and make sure you
have dnsmasq or any other DHCP server running in your system.&lt;/p&gt;
&lt;p&gt;Now the last part is to tell systemd-nspawn to use the bridge
networking interface we have defined. This is done using
&lt;em&gt;container-name.nspawn&lt;/em&gt; file. Put this file under
&lt;em&gt;/etc/systemd/nspawn&lt;/em&gt; folder.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Exec]&lt;/span&gt;
&lt;span class="na"&gt;Boot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;

&lt;span class="k"&gt;[Files]&lt;/span&gt;
&lt;span class="na"&gt;Bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/vasudev/Documents/Python/upstream/apt-offline/&lt;/span&gt;

&lt;span class="k"&gt;[Network]&lt;/span&gt;
&lt;span class="na"&gt;VirtualEthernet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;Bridge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;natbr0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here you can specify networking, and files mounting section of the
container. For full list please refer the &lt;em&gt;systemd.nspawn&lt;/em&gt; manual
page.&lt;/p&gt;
&lt;p&gt;Now all this is done you can happily do&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;machinectl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;container-name
&lt;span class="c1"&gt;#or&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;systemd-nspawn@container-name
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="resource-control"&gt;
&lt;h2&gt;Resource Control&lt;/h2&gt;
&lt;p&gt;Now all things said and done, one last part remains. Yes what is the
point if we can't control how much resource does the container
use. Atleast it is more important for me, because I use old and bit
low powered laptop.&lt;/p&gt;
&lt;p&gt;Systemd provides way to control the resource using Control
interface. To see all the the interfaces exposed by systemd please
refer &lt;em&gt;systemd.resource-control&lt;/em&gt; manual page.&lt;/p&gt;
&lt;p&gt;The way to control the resource is using &lt;em&gt;systemctl&lt;/em&gt;. Once container
starts running we can run following command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;set-property&lt;span class="w"&gt; &lt;/span&gt;container-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CPUShares&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CPUQuota&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MemoryLimit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;500M
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The manual page does say that these things can be put under [Slice]
section of unit files. Now I don't have clear idea if this can be put
under .nspawn files or not. For the sake of persisting the container I
manually wrote the service file for container by copying
systemd-nspawn&amp;#64;.service and adding [Slice]  section. But if I don't
know how to find out if this had any effect or not.&lt;/p&gt;
&lt;p&gt;If some one knows about this please share your suggestions to me and I
will update this section with your provided information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;All in all I like systemd-nspawn a lot. I use it to run container for
development of &lt;em&gt;apt-offline&lt;/em&gt;. I previously used lxc where all can be
controlled using a single config file. But I feel systemd-nspawn is
more tightly integrated with system than lxc.&lt;/p&gt;
&lt;p&gt;There is definitely more in systemd-nspawn than I've currently figured
out. Only thing is its not as popular as other alternatives and
definitely lacks good howto documentation.For now only way out is dig
the manual pages, scratch your head, pull your hair out and figure out
new possibilities in systemd-nspawn. ;-)&lt;/p&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="systemd-nspawn"/><category term="containers"/><category term="debian"/></entry><entry><title>Running Plan9 using 9vx - using vx32 sandboxing library</title><link href="https://copyninja.in/blog/plan9_on_9vx_linux.html" rel="alternate"/><published>2015-02-21T12:32:00+05:30</published><updated>2015-02-21T12:32:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2015-02-21:/blog/plan9_on_9vx_linux.html</id><summary type="html">&lt;p class="first last"&gt;Running Plan9 using 9vx, a vx32 sandboxing library.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Now a days I'm more and more attracted towards Plan9, an Operating
System meant to be the successor of UNIX and created by same people
who created original UNIX. I'm always baffled by the simplicity of
Plan9. Sadly Plan9 never took off for whatever reasons.&lt;/p&gt;
&lt;p&gt;I've been for a while trying to run Plan9, I ran Plan9 on Raspberry Pi
model B using 9pi, but I couldn't experiment with it more due to some
restrictions in my home setup.&lt;/p&gt;
&lt;p&gt;I installed original Plan9 4th Edition from Bell labs (now part of
Alcatel-Lucent), I will write about it in on different post. But
running virtual machine on my system is again PITA as system is
already old (3 and half year). I came across the &lt;a class="reference external" href="http://swtch.com/9vx/"&gt;9vx&lt;/a&gt; which is port of Plan9 for FreeBSD, Linux
and Mac OSX by Russ Cox.&lt;/p&gt;
&lt;p&gt;I downloaded original 9vx version 0.9.12 from Russ's page linked
above. The archive contains a Plan9 rootfs along with precompiled 9vx
binaries for Linux, FreeBSD and Mac OS X. I ran the Linux binary but
it crashed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;./9vx.Linux&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;glenda
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was seeing some illegal instruction error in dmesg. I didn't bother
to do more investigation.&lt;/p&gt;
&lt;p&gt;A bit of googling showed me Arch Linux's &lt;a class="reference external" href="https://wiki.archlinux.org/index.php/9vx"&gt;wiki page on 9vx&lt;/a&gt;. I got errors trying to
compile the original vx32 from &lt;a class="reference external" href="https://bitbucket.org/rsc/vx32"&gt;rsc's repository&lt;/a&gt; but later saw that AUR 9vx package
is built from different repository forked from rsc's found &lt;a class="reference external" href="https://bitbucket.org/rminnich/vx32"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I cloned the repository to local and compiled it, I don't really
remember if I had installed any additional packages. But if you get
error you will know what additional thing is required. After
compilation the 9vx binary is found inside &lt;cite&gt;src/9vx/9vx&lt;/cite&gt;. I used this
newly compiled 9vx to run the the rootfs I downloaded from Russ's
website.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;9vx&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;glenda&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;/path/to/extracted/9vx-0.9.12/
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This launches Plan9 and allows you to work inside Plan9. The good part
is its not resource hungry and still looks like you have a VM running
with Plan9 on it.&lt;/p&gt;
&lt;p&gt;But there seems to be a better way to do this directly from plan9 iso
from bell labs. It can be found on &lt;a class="reference external" href="http://9fans.net/archive/2010/10/14"&gt;9fans list&lt;/a&gt;. Now I'm going to try that out
too :-). And in next post I will share my experience of using Plan9 on
Qemu.&lt;/p&gt;
</content><category term="plan9"/><category term="plan9"/><category term="debian"/><category term="9vx"/></entry><entry><title>Notes: LXC How-To</title><link href="https://copyninja.in/blog/lxc_howto.html" rel="alternate"/><published>2014-12-26T08:11:00+05:30</published><updated>2014-12-26T08:11:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-12-26:/blog/lxc_howto.html</id><summary type="html">&lt;p class="first last"&gt;A short how to on LXC basics&lt;/p&gt;
</summary><content type="html">&lt;p&gt;LXC - Linux Containers allows us to run multiple isolated Linux system
under same control host. This will be useful for testing application
without changing our existing system.&lt;/p&gt;
&lt;p&gt;To create an LXC container we use the &lt;cite&gt;lxc-create&lt;/cite&gt; command, it can
accepts the template option, with which we can choose the OS we would
like to run under the virtual isolated environment. On a Debian system
I see following templates supported&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;vasudev@rudra:&lt;span class="w"&gt; &lt;/span&gt;~/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;/usr/share/lxc/templates
lxc-alpine*&lt;span class="w"&gt;    &lt;/span&gt;lxc-archlinux*&lt;span class="w"&gt;  &lt;/span&gt;lxc-centos*&lt;span class="w"&gt;  &lt;/span&gt;lxc-debian*&lt;span class="w"&gt;    &lt;/span&gt;lxc-fedora*&lt;span class="w"&gt;  &lt;/span&gt;lxc-openmandriva*&lt;span class="w"&gt;  &lt;/span&gt;lxc-oracle*&lt;span class="w"&gt;  &lt;/span&gt;lxc-sshd*&lt;span class="w"&gt;    &lt;/span&gt;lxc-ubuntu-cloud*
lxc-altlinux*&lt;span class="w"&gt;  &lt;/span&gt;lxc-busybox*&lt;span class="w"&gt;    &lt;/span&gt;lxc-cirros*&lt;span class="w"&gt;  &lt;/span&gt;lxc-download*&lt;span class="w"&gt;  &lt;/span&gt;lxc-gentoo*&lt;span class="w"&gt;  &lt;/span&gt;lxc-opensuse*&lt;span class="w"&gt;      &lt;/span&gt;lxc-plamo*&lt;span class="w"&gt;   &lt;/span&gt;lxc-ubuntu*
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For my application testing I wanted to create a Debian container for
my By default the template provided by lxc package creates Debian
stable container. This can be changed by passing the option to
debootstrap after &lt;cite&gt;--&lt;/cite&gt; as shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MIRROR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:9999/debian&lt;span class="w"&gt; &lt;/span&gt;lxc-create&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;debian&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;-f&lt;span class="w"&gt;   &lt;/span&gt;container.conf&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;container-name&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;sid
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;cite&gt;-r&lt;/cite&gt; switch is used to specify the release, MIRROR environment
variable is used to choose the required Debian mirror. I wanted to use
my own local &lt;em&gt;approx&lt;/em&gt; installation, so I can save some bandwidth.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;container.conf&lt;/cite&gt; is the configuration file used for creating the LXC,
in my case it contains basic information on how container networking
should b setup. The configuration is basically taken from &lt;a class="reference external" href="https://wiki.debian.org/LXC"&gt;LXC Debian
wiki&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="na"&gt;lxc.utsname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;aptoffline-dev&lt;/span&gt;
&lt;span class="na"&gt;lxc.network.type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;veth&lt;/span&gt;
&lt;span class="na"&gt;lxc.network.flags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;up&lt;/span&gt;
&lt;span class="na"&gt;lxc.network.link&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;br0.1&lt;/span&gt;
&lt;span class="na"&gt;lxc.network.name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;eth0&lt;/span&gt;
&lt;span class="na"&gt;lxc.network.ipv4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;192.168.3.2/24&lt;/span&gt;
&lt;span class="na"&gt;lxc.network.veth.pair&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;vethvm1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I'm using VLAN setup described in &lt;a class="reference external" href="https://wiki.debian.org/LXC/VlanNetworking"&gt;Debian wiki: LXC VLAN Networking&lt;/a&gt; page. Below is my
&lt;cite&gt;interfaces&lt;/cite&gt; file.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
iface eth0.1 inet manual

iface br0.1  inet manual
   bridge_ports eth0.1
   bridge_fd 0
   bridge_maxwait 0
&lt;/pre&gt;
&lt;p&gt;Before launching the LXC make sure you run below command&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;ifup&lt;span class="w"&gt; &lt;/span&gt;eth0.1
sudo&lt;span class="w"&gt; &lt;/span&gt;ifup&lt;span class="w"&gt; &lt;/span&gt;br0.1

&lt;span class="c1"&gt;# Also give ip to bridge in same subnet as lxc.network.ipv4&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;addr&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.3.1/24&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;br0.1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I'm giving ip address to bridge so that I can communicate with
container from my control host, once it comes up.&lt;/p&gt;
&lt;p&gt;Now start the container using below command&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;lxc-start&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;tty8
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We are starting lxc in daemon mode and attaching it to console
&lt;cite&gt;tty8&lt;/cite&gt;. If you want, you can drop -d and -c option to start lxc in
foreground. But its better you start it in background and attach using
&lt;cite&gt;lxc-console&lt;/cite&gt; command shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;lxc-console&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;tty8
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can detach from console using &lt;cite&gt;Ctrl+a q&lt;/cite&gt; combination and let lxc
execute in background.&lt;/p&gt;
&lt;p&gt;Its also possible to simply ssh into the running container since we
have enabled networking.&lt;/p&gt;
&lt;p&gt;Stopping the container should be done using &lt;cite&gt;lxc-stop&lt;/cite&gt; command, but
without &lt;cite&gt;-k&lt;/cite&gt; switch (kill) this command never returned. Even with
timeout container is not stopped.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;lxc-stop&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;container
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;cite&gt;-r&lt;/cite&gt; can be used for reboot of container. Since I couldn't get clean
shutdown I normally attach the console and issue a &lt;cite&gt;halt&lt;/cite&gt; command in
container itself. Not sure if this is the right way, but it gets the
thing done.&lt;/p&gt;
&lt;p&gt;I consider Linux container as a better alternative for spawning a
virtual Linux environment instead of running a full blown VM like
Virtualbox or VMware.&lt;/p&gt;
</content><category term="devops"/><category term="lxc"/><category term="container"/><category term="debian"/></entry><entry><title>Note to Self: LVM Shrink Resize HowTo</title><link href="https://copyninja.in/blog/lvm-shrink-resize.html" rel="alternate"/><published>2014-10-05T12:00:00+05:30</published><updated>2014-10-05T12:00:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-10-05:/blog/lvm-shrink-resize.html</id><summary type="html">&lt;p class="first last"&gt;Post is a note to self describing LVM shrink and resize of
partition&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Recently I had to reinstall a system at office with Debian Wheezy and
I thought I should use this opportunity to experiment with LVM. Yeah
I've not used LVM till date, even though I'm using Linux for more than
5 years now. I know many DD friends who use LVM with LUKS encryption
and I always wanted to experiment, but since my laptop is only thing
I've and its currently perfectly in shape I didn't dare to experiment
it there. This reinstall was golden opportunity for me to experiment
and learn something new.&lt;/p&gt;
&lt;p&gt;I used Wheezy CD ISO downloaded using &lt;em&gt;jigdo&lt;/em&gt; for installation. Now I
will just go bit off topic and want to share the USB stick
preparation. I have to say this because I had not done installation
for quite a while now. Last I did was during Squeeze time so like
usual I blindly executed following command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;debian-wheezy.iso&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Surprisingly USB stick didn't boot! I was getting &lt;strong&gt;Corrupt or missing
ISO.bin&lt;/strong&gt;. So next I tried using &lt;cite&gt;dd&lt;/cite&gt; for preparing.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;debian-wheezy.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdb
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Surprisingly this also didn't work and I get same error message as
above. This is when I went back to debian manual and looked for
installation step and there I found new way!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;debian-wheezy.iso&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Look at destination, its a device and voilà this worked! This is
something new I learnt and I'm surprised how easy it is now to prepare
USB stick. But I still didn't get why first 2 methods failed!. If you
guys know please do share.&lt;/p&gt;
&lt;p&gt;Now coming back to LVM. I used default LVM when disk partitioning was
asked, and I used guided partitioning method provided by
&lt;cite&gt;debian-installer&lt;/cite&gt; and ended up with following layout&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;lvs
&lt;span class="w"&gt;  &lt;/span&gt;LV&lt;span class="w"&gt;     &lt;/span&gt;VG&lt;span class="w"&gt;        &lt;/span&gt;Attr&lt;span class="w"&gt;     &lt;/span&gt;LSize&lt;span class="w"&gt;  &lt;/span&gt;Pool&lt;span class="w"&gt; &lt;/span&gt;Origin&lt;span class="w"&gt; &lt;/span&gt;Data%&lt;span class="w"&gt;  &lt;/span&gt;Move&lt;span class="w"&gt; &lt;/span&gt;Log&lt;span class="w"&gt; &lt;/span&gt;Copy%&lt;span class="w"&gt;  &lt;/span&gt;Convert
home&lt;span class="w"&gt;   &lt;/span&gt;system-disk&lt;span class="w"&gt; &lt;/span&gt;-wi-ao--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;62&lt;/span&gt;.34g
root&lt;span class="w"&gt;   &lt;/span&gt;system-disk&lt;span class="w"&gt; &lt;/span&gt;-wi-ao--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;.31g
swap_1&lt;span class="w"&gt; &lt;/span&gt;system-disk&lt;span class="w"&gt; &lt;/span&gt;-wi-ao--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.64g
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So guided partitioning of &lt;cite&gt;debian-installer&lt;/cite&gt; allocates 10G for root
and rest to home and swap. This is not a problem but when I started
installing required software, I could see root running out of space
quickly so I wanted to resize root and give it 10G more, for this I
need to reduce the home by 10G for which I need to first unmount the
home partition. Unmounting home from running system isn't possible so
I booted into recovery assuming I can unmount home there but I
couldn't. &lt;cite&gt;lsof&lt;/cite&gt; didn't show any one using /home after searching a bit
I found &lt;cite&gt;fuser&lt;/cite&gt; command and it looks like kernel is using /home which
is mounted by it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;fuser&lt;span class="w"&gt; &lt;/span&gt;-vm&lt;span class="w"&gt; &lt;/span&gt;/home
&lt;span class="w"&gt;                     &lt;/span&gt;USER&lt;span class="w"&gt;        &lt;/span&gt;PID&lt;span class="w"&gt; &lt;/span&gt;ACCESS&lt;span class="w"&gt; &lt;/span&gt;COMMAND
/home:&lt;span class="w"&gt;               &lt;/span&gt;root&lt;span class="w"&gt;     &lt;/span&gt;kernel&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;/home
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So it isn't possible to unmount /home in recovery mode also. Online
materials told me to use live-cd for doing this but I didn't have
patience to do that so I just went ahead commented /home mounting in
/etc/fstab and rebooted!. This time it worked and /home is not mounted
on recovery mode. Now comes the hard part resizing home, thanks to
&lt;a class="reference external" href="http://tldp.org/HOWTO/LVM-HOWTO/reducelv.html"&gt;TLDP doc on reducing&lt;/a&gt; I coud do this with
following step&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# e2fsck -f /dev/volume-name/home&lt;/span&gt;
&lt;span class="c1"&gt;# resize2fs /dev/volume-name/home 52G&lt;/span&gt;
&lt;span class="c1"&gt;# lvreduce -L-10G /dev/volume-name/home&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now the next part live extending the root partition again thanks
to &lt;a class="reference external" href="http://tldp.org/HOWTO/LVM-HOWTO/extendlv.html"&gt;TLDP doc on extending&lt;/a&gt; following command
did it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# lvextend -L+10G /dev/volume-name/root&lt;/span&gt;
&lt;span class="c1"&gt;# resize2fs /dev/volumne-name/root&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now important part! &lt;strong&gt;Uncomment /home line in /etc/fstab so it
will be mounted normally in next boot&lt;/strong&gt; and reboot! On login I can see
my partitions updated.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# lvs&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;LV&lt;span class="w"&gt;     &lt;/span&gt;VG&lt;span class="w"&gt;        &lt;/span&gt;Attr&lt;span class="w"&gt;     &lt;/span&gt;LSize&lt;span class="w"&gt;  &lt;/span&gt;Pool&lt;span class="w"&gt; &lt;/span&gt;Origin&lt;span class="w"&gt; &lt;/span&gt;Data%&lt;span class="w"&gt;  &lt;/span&gt;Move&lt;span class="w"&gt; &lt;/span&gt;Log&lt;span class="w"&gt; &lt;/span&gt;Copy%&lt;span class="w"&gt;  &lt;/span&gt;Convert
home&lt;span class="w"&gt;   &lt;/span&gt;system-disk&lt;span class="w"&gt; &lt;/span&gt;-wi-ao--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;52&lt;/span&gt;.34g
root&lt;span class="w"&gt;   &lt;/span&gt;system-disk&lt;span class="w"&gt; &lt;/span&gt;-wi-ao--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;19&lt;/span&gt;.31g
swap_1&lt;span class="w"&gt; &lt;/span&gt;system-disk&lt;span class="w"&gt; &lt;/span&gt;-wi-ao--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.64g
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've started liking LVM more now! :)&lt;/p&gt;
</content><category term="devops"/><category term="lvm"/><category term="debian-installer"/><category term="partition"/><category term="debian"/></entry><entry><title>Stop messing with my settings Network Manager</title><link href="https://copyninja.in/blog/networkmanager-wifi-issue.html" rel="alternate"/><published>2014-07-20T00:39:00+05:30</published><updated>2014-07-20T00:39:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-07-20:/blog/networkmanager-wifi-issue.html</id><summary type="html">&lt;p class="first last"&gt;Network Manager toying with wifi card&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I use a laptop with &lt;cite&gt;Atheros&lt;/cite&gt; wifi card with &lt;cite&gt;ath9k&lt;/cite&gt; driver. I use
&lt;cite&gt;hostapd&lt;/cite&gt; to convert my laptop wifi into AP (Access point) so I can
share network with my &lt;cite&gt;Nexus 7&lt;/cite&gt; and &lt;cite&gt;Kindle&lt;/cite&gt;. This has been working
fine for quite some time till my recent update.&lt;/p&gt;
&lt;p&gt;After recent system update (I use Debian Sid), I couldn't for some
reason convert my wifi into AP so my device can connect. I can't find
anything in log nor in hostapd debug messages which is useful to
trouble shoot the issue. Every time I start the laptop my wifi card
will be blocked by RF-KILL and I have manually unblock (both hard and
soft). The script which I use to convert my Wifi into AP is below&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;#Initial wifi interface configuration
ifconfig &amp;quot;$1&amp;quot; up 192.168.2.1 netmask 255.255.255.0
sleep 2

# start dhcp
sudo systemctl restart dnsmasq.service

iptables --flush
iptables --table nat --flush
iptables --delete-chain
iptables -t nat -A POSTROUTING -o &amp;quot;$2&amp;quot; -j MASQUERADE
iptables -A FORWARD -i &amp;quot;$1&amp;quot; -j ACCEPT

sysctl -w net.ipv4.ip_forward=1

#start hostapd
hostapd /etc/hostapd/hostapd.conf  &amp;amp;&amp;gt; /dev/null &amp;amp;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I tried rebooting the laptop and for some time I managed to convert my
wifi into AP, I noticed at same time that Network Manager is not
started once laptop is booted, yeah this also started happening after
recent upgrade which I guess is the black magic of systemd. After some
time I noticed wifi has went down and now I can't bring it up because
its blocked by RF-KILL. After checking the syslog I noticed following
lines.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Jul 18 23:09:30 rudra kernel: [ 1754.891060] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; (mon.wlan0): using nl80211 for WiFi device control
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; (mon.wlan0): driver supports Access Point (AP) mode
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; (mon.wlan0): new 802.11 WiFi device (driver: 'ath9k' ifindex: 10)
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; (mon.wlan0): exported as /org/freedesktop/NetworkManager/Devices/8
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; (mon.wlan0): device state change: unmanaged -&amp;gt; unavailable (reason 'managed') [10 20 2]
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; (mon.wlan0): preparing device
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; devices added (path: /sys/devices/pci0000:00/0000:00:1c.1/0000:04:00.0/net/mon.wlan0, iface: mon.wlan0)
Jul 18 23:09:30 rudra NetworkManager[5485]: &amp;lt;info&amp;gt; device added (path: /sys/devices/pci0000:00/0000:00:1c.1/0000:04:00.0/net/mon.wlan0, iface: mon.wlan0): no ifupdown configuration found.
Jul 18 23:09:33 rudra ModemManager[891]: &amp;lt;warn&amp;gt;  Couldn't find support for device at '/sys/devices/pci0000:00/0000:00:1c.1/0000:04:00.0': not supported by any plugin
&lt;/pre&gt;
&lt;p&gt;Well I couldn't figure out much but it looks like NetworkManager has
come up and after seeing interface &lt;cite&gt;mon.wlan0&lt;/cite&gt;, a monitoring interface
created by &lt;cite&gt;hostapd&lt;/cite&gt; to monitor the AP goes mad and tries to do
something with it. I've no clue what it is doing and don't have enough
patience to debug that. Probably some expert can give me hints on
this.&lt;/p&gt;
&lt;p&gt;So as a last resort I purged the NetworkManager completely from the
system and settled back to good old &lt;cite&gt;wicd&lt;/cite&gt; and rebooted the
system. After reboot wifi card is happy and is not blocked by RF-KILL
and now I can convert it AP and use it as long as I wish without any
problems. Wicd is not a great tool but its good enough to get the job
done and does only what is asked to it unlike the NetworkManager.&lt;/p&gt;
&lt;p&gt;So in short&lt;/p&gt;
&lt;blockquote&gt;
NetworkManager please stop f***ing with my settings and stop acting
oversmart.&lt;/blockquote&gt;
</content><category term="misc"/><category term="network-manager"/><category term="ath9k"/><category term="wifi"/></entry><entry><title>Exposing function in python module using entry_points, WSME in a Flask webapp</title><link href="https://copyninja.in/blog/entry_point_wsme.rst.html" rel="alternate"/><published>2014-06-07T18:10:00+05:30</published><updated>2014-06-07T18:10:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-06-07:/blog/entry_point_wsme.rst.html</id><summary type="html">&lt;p class="first last"&gt;In this post I try to explain how to expose a function in a
python module as REST service using WSME from an Flask
application using setuptools entry_points feature.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The heading might be ambiguous, but I couldn't figure out better
heading so let me start by explaining what I'm trying to solve here.&lt;/p&gt;
&lt;div class="section" id="problem"&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;I have a python module which contains a function which I want to
expose as a REST web service in a Flask application. I use WSME for
Flask application, which actually needs signature of function in
question and problem comes to picture because function to be exposed
is foreign to Flask application, it resides in separate python module.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="solution"&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;While reading &lt;a class="reference external" href="http://julien.danjou.info/"&gt;Julien Danjou's&lt;/a&gt; &lt;em&gt;Hackers
Guide To Python&lt;/em&gt; book I came across the setuptools &lt;cite&gt;entry_points&lt;/cite&gt;
concept which can be used to extend existing feature of a tool like
plug-ins. So here I'm going to use this &lt;cite&gt;entry_points&lt;/cite&gt; feature from
setuptools to provide function in the module which can expose the
signature of function[s] to be exposed through REST. Of course this
means I need to modify module in question to write entry_points and
function for giving out signature of function to be exposed.&lt;/p&gt;
&lt;p&gt;I will explain this with small example. I have a dummy module which
provides a add function and a function which exposes the add functions
signature.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expose_rest_func&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is stored in &lt;cite&gt;dummy/__init__.py&lt;/cite&gt; file. I use &lt;cite&gt;pbr&lt;/cite&gt; tool to
package my python module. Below is content of &lt;cite&gt;setup.cfg&lt;/cite&gt; file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vasudev&lt;/span&gt; &lt;span class="n"&gt;Kamath&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kamathvasudev&lt;/span&gt;&lt;span class="nd"&gt;@gmail&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Dummy&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;testing&lt;/span&gt; &lt;span class="n"&gt;purpose&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;span class="n"&gt;license&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MIT&lt;/span&gt;
&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;README&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rst&lt;/span&gt;
&lt;span class="n"&gt;requires&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.7&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;dummy&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;entry_points&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;expose_rest_func&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The special thing in above file is &lt;cite&gt;entry_points&lt;/cite&gt; section, which
defines function to be hooked into entry_point. In our case
entry_point &lt;cite&gt;myapp.api.rest&lt;/cite&gt; is used by our Flask application to
interact with modules which expose them. The function which will be
got accessing the entry_point is &lt;cite&gt;expose_rest_func&lt;/cite&gt; which gives the
function to be exposed its arg types and return types as a list.&lt;/p&gt;
&lt;p&gt;If we are looking at only supporting python3 it was sufficient to know
function name only and use &lt;a class="reference external" href="http://legacy.python.org/dev/peps/pep-3107"&gt;function annotations&lt;/a&gt; in function
definition. Since I want to support both python2 and python3 this is
out of question.&lt;/p&gt;
&lt;p&gt;Now, just run the following command in virtualenv to get the module
installed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="go"&gt;PBR_VERSION=0.1 python setup.py sdist&lt;/span&gt;
&lt;span class="go"&gt;pip install dist/dummy_module-0.1.tar.gz&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now if you want to see if the module is exposing entry_point or not
just use &lt;cite&gt;entry_point_inspector&lt;/cite&gt; tool after installing you will get a
command called &lt;cite&gt;epi&lt;/cite&gt; if you run it as follows you should note the
dummy_module in its output&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="go"&gt;epi group list&lt;/span&gt;
&lt;span class="go"&gt;+-----------------------------+&lt;/span&gt;
&lt;span class="go"&gt;| Name                        |&lt;/span&gt;
&lt;span class="go"&gt;+-----------------------------+&lt;/span&gt;
&lt;span class="go"&gt;| cliff.formatter.completion  |&lt;/span&gt;
&lt;span class="go"&gt;| cliff.formatter.list        |&lt;/span&gt;
&lt;span class="go"&gt;| cliff.formatter.show        |&lt;/span&gt;
&lt;span class="go"&gt;| console_scripts             |&lt;/span&gt;
&lt;span class="go"&gt;| distutils.commands          |&lt;/span&gt;
&lt;span class="go"&gt;| distutils.setup_keywords    |&lt;/span&gt;
&lt;span class="go"&gt;| egg_info.writers            |&lt;/span&gt;
&lt;span class="go"&gt;| epi.commands                |&lt;/span&gt;
&lt;span class="go"&gt;| flake8.extension            |&lt;/span&gt;
&lt;span class="go"&gt;| setuptools.file_finders     |&lt;/span&gt;
&lt;span class="go"&gt;| setuptools.installation     |&lt;/span&gt;
&lt;span class="go"&gt;| myapp.api.rest              |&lt;/span&gt;
&lt;span class="go"&gt;| stevedore.example.formatter |&lt;/span&gt;
&lt;span class="go"&gt;| stevedore.test.extension    |&lt;/span&gt;
&lt;span class="go"&gt;| wsme.protocols              |&lt;/span&gt;
&lt;span class="go"&gt;+-----------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So our entry_point is exposed now, we need to access it in our Flask
application and expose the function using WSME. It is done by below
code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;wsmeext.flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pkg_resources&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
   &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;DEBUG&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entrypoint&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pkg_resources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter_entry_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;myapp.api.rest&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="c1"&gt;# Ugly but fix is only supporting python3&lt;/span&gt;
       &lt;span class="n"&gt;func_signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entrypoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()()&lt;/span&gt;
       &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;func_signature&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;
           &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func_signature&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
               &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;func_signature&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;&lt;span class="n"&gt;func_signature&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
   &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;entry_point &lt;cite&gt;myapp.api.rest&lt;/cite&gt; are iterated using the pkg_resources
package provided by setuptools, when I load the entry_point I get back
the function to be used which is called in same place to get function
signature. Then I'm calling Flask and WSME decorator functions (yeah
instead of decorating I'm using them directly over function to be
exposed).&lt;/p&gt;
&lt;p&gt;The code looks bit ugly at the place where I'm accessing list using
slices but I can't help it due to limitation of python2 with python3
there is new packing and unpacking stuff which makes code look bit
more cooler see below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;wsmeext.flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pkg_resources&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;DEBUG&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entrypoint&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pkg_resources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter_entry_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;silpa.api.rest&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rettype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entrypoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()()&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;
        &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rettype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;func_signature&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can access the service at &lt;cite&gt;http://localhost:5000/add&lt;/cite&gt; depending on
&lt;cite&gt;Accept&lt;/cite&gt; header of HTTP you will get either XML or JSON response. If
you access it from browser you will get XML response.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="usecase"&gt;
&lt;h2&gt;Usecase&lt;/h2&gt;
&lt;p&gt;Now if you are wondering what is the reason behind this experience,
this is for &lt;a class="reference external" href="http://silpa.org.in"&gt;SILPA Project&lt;/a&gt;. I'm trying to
implement REST service for all Indic language computing module. Since
all these module are independent of SILPA which is a Flask web app I
had to find a way to achieve this, and this is what I came up with.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I'm not sure if there is any other approaches to achieve this, if
there I would love to hear about them. You can write your comments and
suggestion over &lt;a class="reference external" href="http://scr.im/vasudev"&gt;email&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="development"/><category term="python"/><category term="programming"/><category term="wsme"/><category term="rest"/><category term="setuptools"/></entry><entry><title>Using WSME with Flask microframework</title><link href="https://copyninja.in/blog/wsme-with-flask.html" rel="alternate"/><published>2014-06-03T20:15:00+05:30</published><updated>2014-06-03T20:15:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-06-03:/blog/wsme-with-flask.html</id><summary type="html">&lt;p class="first last"&gt;This is short guide on how to use wsme with Flask
applications, writing this because I felt documentation is
lacking.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;After reading &lt;a class="reference external" href="http://julien.danjou.info"&gt;Julien Danjou's&lt;/a&gt; I found
out WSME (Web Service Made Easy) a Python framework which allows us to
easily create Web Services in Python. For &lt;a class="reference external" href="http://silpa.org.in"&gt;SILPA&lt;/a&gt; we needed a REST like interface and I thought
of giving it try as WSME readily advertised the Flask integration, and
this post was born when I read the documentation for Flask
integration.&lt;/p&gt;
&lt;p&gt;First of all Flask is a nice framework which will right way allow
development of REST api for simple purposes, but my requirement was
bit complicated where I had to expose function in a separate python
modules through SILPA. I think detailed requirement can be part of
another post, so let me explain how to use WSME with Flask app.&lt;/p&gt;
&lt;p&gt;WSME integration with Flask is done via decorator function
&lt;cite&gt;wsmeext.flask.signature&lt;/cite&gt; which expects you to provide it with
signature of function to expose. And &lt;a class="reference external" href="http://wsme.readthedocs.org/en/latest/integrate.html#wsmeext.flask.signature"&gt;here&lt;/a&gt;
is its documentation, basically signature of &lt;cite&gt;signature&lt;/cite&gt; function is&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;wsmeext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg_types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Yeah thats all docs have sadly.&lt;/p&gt;
&lt;p&gt;So basically exposing is the only thing WSME handles for us here,
routing and other stuffs need to be done by Flask itself. So lets
consider a example, simple function to add as shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For providing REST like service, all you need below code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;wsmeext.flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/add&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So first argument to &lt;cite&gt;signature&lt;/cite&gt; is return type of function and rest
arguments are the argument to function to be exposed. Now you can
access the newly exposed service by visiting
&lt;em&gt;http://localhost:5000/add&lt;/em&gt; but don't forget to pass the arguments
either via query string or through post. You can restrict methods of
access via Flask's &lt;cite&gt;route&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;So what's the big deal of not having docs right?.. Well fun part began
when we use bit more complex return type like &lt;em&gt;dictionaries&lt;/em&gt; or
&lt;em&gt;lists&lt;/em&gt; . Below is modified code I'm using to demonstrate problem I
faced during using &lt;cite&gt;dict&lt;/cite&gt; as return type.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;wsmeext.flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/add&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;result&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Basically I'm returning a dictionary containing result now, for
demonstration purpose. When I run the application &lt;strong&gt;boom&lt;/strong&gt; python
barked at me with following message.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gt"&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class="x"&gt;File &amp;quot;wsme_dummy.py&amp;quot;, line 7, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt; @signature(dict, int, int)&lt;/span&gt;
&lt;span class="x"&gt;File &amp;quot;c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsmeext\flask.py&amp;quot;, line 48, in decorator&lt;/span&gt;
&lt;span class="x"&gt; funcdef.resolve_types(wsme.types.registry)&lt;/span&gt;
&lt;span class="x"&gt;File &amp;quot;c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsme\api.py&amp;quot;, line 109, in resolve_types&lt;/span&gt;
&lt;span class="x"&gt; self.return_type = registry.resolve_type(self.return_type)&lt;/span&gt;
&lt;span class="x"&gt;File &amp;quot;c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsme\types.py&amp;quot;, line 739, in resolve_type&lt;/span&gt;
&lt;span class="x"&gt; type_ = self.register(type_)&lt;/span&gt;
&lt;span class="x"&gt;File &amp;quot;c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsme\types.py&amp;quot;, line 668, in register&lt;/span&gt;
&lt;span class="x"&gt; class_._wsme_attributes = None&lt;/span&gt;
&lt;span class="x"&gt;TypeError: can&amp;#39;t set attributes of built-in/extension type &amp;#39;dict&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After going through code from files involved in above traces this is
what I found&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;cite&gt;wsmeext.flask.signature&lt;/cite&gt; inturn uses &lt;cite&gt;wsme.signature&lt;/cite&gt; which is
just alias of &lt;cite&gt;wsme.api.signature&lt;/cite&gt;.&lt;/li&gt;
&lt;li&gt;Link in documentation in sentence &lt;em&gt;See &amp;#64;signature for parameter
documentation&lt;/em&gt; is broken and should actually link to
&lt;cite&gt;wsme.signature&lt;/cite&gt; in docs.&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;wsme.signature&lt;/cite&gt; actually calls &lt;cite&gt;resolve_type&lt;/cite&gt; to check on types of
return and arguments. This function checks if types are instance of
&lt;cite&gt;dict&lt;/cite&gt; or &lt;cite&gt;list&lt;/cite&gt; in such cases it creates instances of
&lt;cite&gt;wsme.type.DictType&lt;/cite&gt; and &lt;cite&gt;wsme.type.ArrayType&lt;/cite&gt; respectively with
values from the argument.&lt;/li&gt;
&lt;li&gt;When I just passed built-in type &lt;cite&gt;dict&lt;/cite&gt; the control went to else
part which just passed the type to &lt;cite&gt;wsme.type.Register.registry&lt;/cite&gt;
function which tries to set the attribute &lt;cite&gt;_wsme_attribute&lt;/cite&gt; which
actually raises &lt;cite&gt;TypeError&lt;/cite&gt; as we can't set attribute for built-in
types.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So by inspecting code of &lt;cite&gt;wsme.type.Registry.resolve_type&lt;/cite&gt; and
&lt;cite&gt;wsme.type.Registry.register&lt;/cite&gt; its clear that what signature expects
when arguments or return type is dictionary/list is instance of
dictionary/list with &lt;cite&gt;type&lt;/cite&gt; of value in it. May be sentence is bit
vague but I'm not sure how to put it more clearly, as an example in
our case add function returns dictioanry with key as string and value
as int, so return type argument for signature will be &lt;cite&gt;{str:
int}&lt;/cite&gt;. Similarly if you return array with int values it will be
&lt;cite&gt;[int]&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;With above understanding our add function now looks like below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@signature&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;result&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and now code worked just fine!. What I couldn't figure out here is
there is no way to have &lt;cite&gt;tuple&lt;/cite&gt; as return value or argument, but I
guess that is not big deal.&lt;/p&gt;
&lt;p&gt;So immidiate task for me after finding this is fix the link in
documentation to point to &lt;cite&gt;wsme.signature&lt;/cite&gt; and probably put some note
some where in documentation about above finding.&lt;/p&gt;
</content><category term="development"/><category term="python"/><category term="programming"/><category term="wsme"/><category term="rest"/></entry><entry><title>Enabling DNSSEC for copyninja.info</title><link href="https://copyninja.in/blog/dnssec-copyninja-dot-info.html" rel="alternate"/><published>2014-05-13T20:30:00+05:30</published><updated>2014-05-13T20:30:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-05-13:/blog/dnssec-copyninja-dot-info.html</id><summary type="html">&lt;p class="first last"&gt;Post describes how I moved copyninja.info domain name
records to DNSSEC.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Recently I've been seeing lot of posts about DNSSEC on Internet and I
thought  I should configure my domain to be secured by DNSSEC.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;copyninja.info&lt;/strong&gt; domain is now secured with DNSSEC you can verify
this by &lt;a class="reference external" href="http://dnssec-debugger.verisignlabs.com/copyninja.info"&gt;DNSSEC analyzer by Verisign&lt;/a&gt; and &lt;a class="reference external" href="http://dnsviz.net/d/copyninja.info/dnssec/"&gt;DNSViz&lt;/a&gt; online tool or by
installing &lt;a class="reference external" href="http://dnssec-validator.cz/"&gt;DNSSEC validator addon&lt;/a&gt; for
your browser.&lt;/p&gt;
&lt;p&gt;There are good amount of tutorials and guides available to enable
DNSSEC for your domain, still I want to note down steps I followed to
here for the record (of course it will be helpful for me if I forget
it ;-))&lt;/p&gt;
&lt;p&gt;First step will be installing &lt;cite&gt;bind9&lt;/cite&gt; and &lt;cite&gt;dnssec-tools&lt;/cite&gt; package, if
you use aptitude installing &lt;cite&gt;dnssec-tools&lt;/cite&gt; will pull down the &lt;cite&gt;bind9&lt;/cite&gt;
unless you have configured aptitude to not install the &lt;strong&gt;Recommends&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Next setting up the zone file for your domain, for this first make a
copy of /etc/bind/db.local as /etc/bind/db.example.com, replace
example.com with your domain name. Now you need to add your zone
records to the zone file.&lt;/p&gt;
&lt;p&gt;Next edit the /etc/bind/named.conf.local file and add following lines&lt;/p&gt;
&lt;pre class="literal-block"&gt;
zone &amp;quot;example.com&amp;quot; {
    type master;
    file &amp;quot;/etc/bind/db.copyninja.info&amp;quot;;
    allow-transfer {secondary;};
};
&lt;/pre&gt;
&lt;p&gt;Here replace secondary with your secondary DNS servers, if you don't
have one you can ommit this but its always recommended to have
secondary DNS servers for a zone, in cases when primary fails. After
this we need to enable DNSSEC on bind, this is done by editing the
file /etc/bind/named.conf.options. Add following lines into
&lt;strong&gt;options&lt;/strong&gt; section.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
dnssec-validation yes;
dnssec-enable yes;
dnssec-lookaside auto;
&lt;/pre&gt;
&lt;p&gt;A more explanation on this can be found on &lt;a class="reference external" href="http://www.linuxjournal.com/content/dnssec-part-ii-implementation"&gt;Linux Journal article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now its time to create DNSSEC keys and sign your zone, more about
different DNSSEC keys and records can be found in the &lt;a class="reference external" href="http://www.linuxjournal.com/content/dnssec-part-i-concepts"&gt;Linux Journal
Article on implementation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I used &lt;cite&gt;zonesigner&lt;/cite&gt; utility from dnssec-tools which does job of
signing and including KSK and ZSK keys into bind configuration which
otherwise should be done manually. Here is the command line I used for
generating keys, thanks to &lt;a class="reference external" href="http://dr.jones.dk"&gt;Jonas&lt;/a&gt; for this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/etc/bind/keys
zonesigner&lt;span class="w"&gt; &lt;/span&gt;-algorithm&lt;span class="w"&gt; &lt;/span&gt;RSASHA256&lt;span class="w"&gt; &lt;/span&gt;-keydirectory&lt;span class="w"&gt; &lt;/span&gt;/etc/bind/keys&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;-dsdir&lt;span class="w"&gt; &lt;/span&gt;/etc/bind/keys&lt;span class="w"&gt; &lt;/span&gt;-archivedir&lt;span class="w"&gt; &lt;/span&gt;/etc/bind/keys/archive&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;/etc/bind/db.example.com
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we store our keys into /etc/bind/keys directory, and use
&lt;strong&gt;RSASHA256&lt;/strong&gt; algorithm for key generation which is more stronger than
the default used RSASHA1 (atleast thats what Jonas told me). This will
create ZSK and KSK for the signing zone and creates a signed zone file
db.example.com.signed in same directory as original zone file. Now all
you need to do is replace the zone file from db.example.com to
db.example.com.signed in &lt;em&gt;file&lt;/em&gt; directive with your &lt;cite&gt;named.conf.local&lt;/cite&gt;
file.&lt;/p&gt;
&lt;blockquote&gt;
Note that this keys expire after 30 days so you need to resign your
zone before 30 days. For resigning just run zonesigner from
/etc/bind/keys. You can setup cron job to do this periodically.&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;zonesigner&lt;span class="w"&gt; &lt;/span&gt;-zone&lt;span class="w"&gt; &lt;/span&gt;example.com&lt;span class="w"&gt; &lt;/span&gt;/path/to/db.example.com
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our signed zone is ready but we are not done yet! For DNSSEC to work
others should trust your signed record for this you need to register
your public keys with registrar for your domain and this can be done
via your domain provider (in my case this is Gandi).&lt;/p&gt;
&lt;p&gt;You need to check your domain name providers documentation on how to
do this. For Gandi users there is a nice &lt;a class="reference external" href="http://wiki.gandi.net/en/domains/dnssec"&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="reference"&gt;
&lt;h2&gt;Reference&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.linuxjournal.com/content/dnssec-part-i-concepts"&gt;Linux  Journal - DNSSEC concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.linux-journal.com/content/dnssec-part-ii-implementation"&gt;Linux Journal - DNSSEC implementation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.dnssec-tools.org/wiki/index.php/Sign_Your_Zone"&gt;Signing your zone&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content><category term="devops"/><category term="dnssec"/><category term="sysadmin"/><category term="technology"/></entry><entry><title>Note to Self: How to use url_for in Flask application</title><link href="https://copyninja.in/blog/using-url-for-in-flask.html" rel="alternate"/><published>2014-05-02T11:50:00+05:30</published><updated>2014-05-02T11:50:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-05-02:/blog/using-url-for-in-flask.html</id><summary type="html">&lt;p class="first last"&gt;Just a note to self on how to use url_for in Flask
application and jinja2 template system.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;cite&gt;url_for&lt;/cite&gt; is normally used to avoid hard coding of URL in Flask based
webapps. I've been using it in SILPA &lt;a class="reference external" href="https://github.com/Project-SILPA/Silpa-Flask"&gt;port&lt;/a&gt; written using Flask
by. But this was written long back and written as POC to show for
Santhosh author of SILPA app which even managed to go into production
:-). Recently I started organizing the code and started using
&lt;cite&gt;flask.Blueprint&lt;/cite&gt; which was previously written using
&lt;cite&gt;flask.views.MethodView&lt;/cite&gt; class and here I started facing problem with
old templates. I'm just gonna explain what is the difference when
using url_for with &lt;cite&gt;MethodView&lt;/cite&gt; and &lt;cite&gt;Blueprint&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Lets have some sample code for &lt;cite&gt;MethodView&lt;/cite&gt; first, this code is from
&lt;cite&gt;Flask&lt;/cite&gt; documentation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MethodView&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MethodView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

       &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
           &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
           &lt;span class="o"&gt;...&lt;/span&gt;

       &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
           &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_form_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_url_rule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/users/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;view_func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UserAPI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;users&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we have a view which is derived from &lt;cite&gt;MethodView&lt;/cite&gt; which has logic
on how to handle the requests. We use &lt;cite&gt;add_url_rule&lt;/cite&gt; to register rule
to handle &lt;cite&gt;/users/&lt;/cite&gt; url end point and we pass the class as view
function which is done by &lt;cite&gt;as_view&lt;/cite&gt; class method and we can refer this
method in our Jinja2 templates using name &lt;cite&gt;users&lt;/cite&gt;. So a statement like&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;users&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;in our templates will be converted to &lt;cite&gt;/users/&lt;/cite&gt; URL when page is
rendered to client by Flask.&lt;/p&gt;
&lt;p&gt;Now when I replaced the &lt;cite&gt;MethodView&lt;/cite&gt; in favor of &lt;cite&gt;Blueprint&lt;/cite&gt; I started
getting up &lt;cite&gt;werkzeug.routing.BuildError&lt;/cite&gt; thrown on my face and I had
no clue why!. Yeah I know I'm bad at reading documentation but even
after reading documentation I was still thinking that&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;should return me a proper URL and I was wondering why its
failing. Finally after re-reading documentation for &lt;cite&gt;url_for&lt;/cite&gt; it was
becoming clear to me, &lt;cite&gt;url_for&lt;/cite&gt; definition looks like below&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here &lt;cite&gt;endpoint&lt;/cite&gt; is actually a function which is supposed to be serving
the URL and &lt;cite&gt;**values&lt;/cite&gt; is the arguments for this function. The URL in
question should be defined in python code using decorator. In my case
following is the new function serving the web pages for SILPA.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;bp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Blueprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;frontend&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@bp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defaults&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;page&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;index.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@bp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;page&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;serve_pages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;index.html&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;index.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;SILPA&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;main_page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_modulename_to_display&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;License&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;license.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;SILPA License&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;main_page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_modulename_to_display&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Credits&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;credits.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Credits&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;main_page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_modulename_to_display&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Contact&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;contact.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Contact SILPA Team&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;main_page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_modulename_to_display&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# modules requested!.&lt;/span&gt;
           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_display_module_map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_display_module_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;main_page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                    &lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_modulename_to_display&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="c1"&gt;# Did we encounter something which is not registered by us?&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can ignore function code but just note the decorators, here I'm
registering the function &lt;cite&gt;serve_pages&lt;/cite&gt; with &lt;cite&gt;page&lt;/cite&gt; as argument for URL
patterns &lt;cite&gt;/&lt;/cite&gt; and &lt;cite&gt;/&amp;lt;page&amp;gt;&lt;/cite&gt;, &lt;cite&gt;_BASE_URL&lt;/cite&gt; here is mount point of
application it can be just &lt;cite&gt;/&lt;/cite&gt; or &lt;cite&gt;/mountpoint&lt;/cite&gt; depending on that URL
registered changes. Now I need to modify code for all &lt;cite&gt;url_for&lt;/cite&gt; in my
template to look like below&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.serve_pages&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/License&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# for /License&lt;/span&gt;
&lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.serve_pages&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# which will turn in to /index.html&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;cite&gt;.&lt;/cite&gt; in front of function is for referring current Blueprint, in my
case the Flask will consider it as &lt;cite&gt;frontend.serve_pages&lt;/cite&gt; as function
name and generates appropriate URL at run time.&lt;/p&gt;
&lt;p&gt;So my fault was misunderstanding &lt;cite&gt;endpoint&lt;/cite&gt; argument as URL endpoint
but where as its actually function name supposed to serve the
page. But when using MethodViews I can simply convert class to a
function with my preferred name just like &lt;cite&gt;UserAPI.as_view('/')&lt;/cite&gt; so
&lt;cite&gt;url_for('/')&lt;/cite&gt; just works.&lt;/p&gt;
</content><category term="development"/><category term="python"/><category term="programming"/><category term="flask"/><category term="webapp"/><category term="notetoself"/></entry><entry><title>Loading Python modules/plug-ins at runtime</title><link href="https://copyninja.in/blog/dynamic-module-loading.html" rel="alternate"/><published>2014-04-07T21:55:00+05:30</published><updated>2014-04-07T21:55:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-04-07:/blog/dynamic-module-loading.html</id><summary type="html">&lt;p class="first last"&gt;Post describes about loading arbitrary python files or
modules during runtime.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Some times it is desired to load arbitrary python files or pre-
installed python modules during application run time.I had encountered
2 such usecases, one is in &lt;a class="reference external" href="http://silpa.org.in"&gt;SILPA application&lt;/a&gt;
and other is &lt;a class="reference external" href="https://github.com/copyninja/dictionary-bot"&gt;dictionary-bot&lt;/a&gt; which I was
refactoring recently.&lt;/p&gt;
&lt;div class="section" id="case-1-loading-installed-python-module"&gt;
&lt;h2&gt;Case 1: Loading installed python module&lt;/h2&gt;
&lt;p&gt;In case of SILPA I need to load pre-installed modules and here is the
&lt;a class="reference external" href="https://github.com/Project-SILPA/Silpa-Flask/blob/master/core/modulehelper.py#L24"&gt;old code&lt;/a&gt;
, that is a bit hacky code I copied from Active State Python
recipies. I found a bit better way to do it using &lt;cite&gt;importlib&lt;/cite&gt; module
as shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;print_function&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;importlib&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;importlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;import_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ImportError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Failed to load &lt;/span&gt;&lt;span class="si"&gt;{module}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;modulename&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                     &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here &lt;cite&gt;importlib&lt;/cite&gt; itself takes care of checking if modulename is
already loaded by checking &lt;cite&gt;sys.modules[modulename]&lt;/cite&gt;, if loaded it
returns that value, otherwise it loads the module and sets it to
&lt;cite&gt;sys.modules[modulename]&lt;/cite&gt; before returning module itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="case-2-loading-python-files-from-arbitrary-location"&gt;
&lt;h2&gt;Case 2: Loading python files from arbitrary location&lt;/h2&gt;
&lt;p&gt;In case of dictionary bot my requirement was bit different, I had some
python files lying around in a directory, which I wanted to plug into
the bot during run time and use them depending on some conditions. So
basic structure which I was looking was as follows.&lt;/p&gt;
&lt;pre&gt;
      pluginloader.py
      plugins
      |
      |__ aplugin.py
      |
      |__ bplugin.py
&lt;/pre&gt;&lt;p&gt;&lt;cite&gt;pluginloader.py&lt;/cite&gt; is the file which needs to load python files under
&lt;cite&gt;plugins&lt;/cite&gt; directory. This was again done using &lt;cite&gt;importlib&lt;/cite&gt; module as
shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;importlib&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_plugins&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;pysearchre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.py$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IGNORECASE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pluginfiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pysearchre&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                                 &lt;span class="s1"&gt;&amp;#39;plugins&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;form_module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form_module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pluginfiles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# import parent module / namespace&lt;/span&gt;
    &lt;span class="n"&gt;importlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;import_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;plugins&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                 &lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;importlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;import_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;plugins&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;modules&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Above code first searches for all python file under specified
directory and creates a relative module name from it. For eg. file
&lt;cite&gt;aplugin.py&lt;/cite&gt; will become &lt;cite&gt;.aplugin&lt;/cite&gt;. Before loading modules itself we
will load the parent module in our case &lt;cite&gt;plugins&lt;/cite&gt;, this is because
&lt;strong&gt;relative imports in python expects parent module to be already
loaded&lt;/strong&gt;. Finally for relative imports to work with
&lt;cite&gt;importlib.import_module&lt;/cite&gt; we need to specify parent module name in
&lt;cite&gt;package&lt;/cite&gt; argument. Note that we ignore files begining with &lt;em&gt;__&lt;/em&gt;, or
specifically we don't want to import __init__.py, this will be done
when we import parent module.&lt;/p&gt;
&lt;p&gt;The above code was inspired from a &lt;a class="reference external" href="https://stackoverflow.com/a/3381582"&gt;answer on StackOverflow&lt;/a&gt;, which uses &lt;cite&gt;imp&lt;/cite&gt; module, I
avoided &lt;cite&gt;imp&lt;/cite&gt; because its been deprecated from &lt;em&gt;Python 3.4&lt;/em&gt; in favor
of &lt;cite&gt;importlib&lt;/cite&gt; module.&lt;/p&gt;
&lt;/div&gt;
</content><category term="development"/><category term="python"/><category term="modules"/><category term="import"/><category term="programming"/><category term="importlib"/></entry><entry><title>Working around type system of Go with unsafe</title><link href="https://copyninja.in/blog/workaround-gotypesystems.html" rel="alternate"/><published>2014-03-12T22:22:00+05:30</published><updated>2014-03-12T22:22:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-03-12:/blog/workaround-gotypesystems.html</id><summary type="html">&lt;p class="first last"&gt;Working around Go type system and converting Go type to byte
slice and interacting with C types in  using unsafe package.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Go language has a strong type system unlike C, and some times this
will be head ache when we want to interact with C data types with Cgo
or just to convert a Go type to lets say byte slice. I recently faced
the same problem and after poking around things, I learned the Go
provides &lt;em&gt;unsafe&lt;/em&gt; package which can be used to work around the Go's
type system.&lt;/p&gt;
&lt;div class="section" id="problem"&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;Recently I started using &lt;em&gt;Cgo&lt;/em&gt; to use some C library I had to write
some tools for development and testing. The reason I chose &lt;em&gt;Go&lt;/em&gt; for
this was prototyping and writing some quick tools is much easier in Go
than done in C.&lt;/p&gt;
&lt;p&gt;The C library had some function which takes pointer to array types and
fills it with some values. The problem I was facing here was how to
create a C array in Go. Go does have array but its largely used as
internal representation for much efficient type called &lt;em&gt;slice&lt;/em&gt; and I
can't directly cast a byte slice into an C array.&lt;/p&gt;
&lt;p&gt;Second problem I had was I had to store arbitrary Go types like float
(float32,float64) and int (int32, int64) etc. into C array.&lt;/p&gt;
&lt;p&gt;So in brief, the problems that needed to solve are&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Find a way to convert byte slice from Go into C array and vice
versa.&lt;/li&gt;
&lt;li&gt;Find a way to convert and store Go types into a C array.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="solution"&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;Basically C array are sequence of memory location which can be
statically or dynamically allocated. In &lt;em&gt;Cgo&lt;/em&gt; its possible to access C
standard library functions for memory allocation, so why not use
it. The memory allocation function then returns the pointer to
starting of allocated memory, we can use this pointer to write Go's
bytes into the memory location and bytes from memory location into
Go's slice.&lt;/p&gt;
&lt;p&gt;The pointer returned by C allocation functions are not directly usable
for memory dereferencing in Go, here is where &lt;em&gt;unsafe&lt;/em&gt; package kicks
in. We will cast the return of C allocation function as
&lt;em&gt;unsafe.Pointer&lt;/em&gt; type and from the documentation of unsafe package,&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;A pointer value of any type can be converted to a Pointer.&lt;/li&gt;
&lt;li&gt;A Pointer can be converted to a pointer value of any type.&lt;/li&gt;
&lt;li&gt;A uintptr can be converted to a Pointer.&lt;/li&gt;
&lt;li&gt;A Pointer can be converted to a uintptr.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;So we can then cast unsafe.Pointer to &lt;em&gt;uintptr&lt;/em&gt; which is the Go type
which is large enough to hold any memory address in Go and can be used
for pointer arithmetic just like we do in C (of course with some more
castings).&lt;/p&gt;
&lt;p&gt;Below I'm pasting a simplified code in C which I wrote for this
post.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#ifndef __BYTETEST_H__&lt;/span&gt;
&lt;span class="cp"&gt;#define __BYTETEST_H__&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UBYTE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ArrayReadFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UBYTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arrayout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ArrayWriteFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UBYTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arrayin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;quot;bytetest.h&amp;quot;&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ArrayReadFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UBYTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arrayout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;UBYTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrayout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ArrayWriteFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UBYTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arrayin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;UBYTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arrayin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Byte slice array received from Go:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%d &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Functions are written just for this post and they don't really do
anything. As you can see &lt;cite&gt;ArrayReadFunc&lt;/cite&gt; takes a pointer to array and
fills it with content of another array using &lt;cite&gt;memcpy&lt;/cite&gt;. Function
&lt;cite&gt;ArrayWriteFunc&lt;/cite&gt; on other hand takes pointer to array and copies its
content to internal array. I've added print logic to &lt;cite&gt;ArrayWriteFunc&lt;/cite&gt;
just to show that values passed from &lt;em&gt;Go&lt;/em&gt; are making it here.&lt;/p&gt;
&lt;p&gt;Below is the Go code which uses the above C files passes byte slice to
get value out of C code and array made of byte slice to C function to
send values in.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;

&lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;#cgo CFLAGS: -std=c99&lt;/span&gt;

&lt;span class="cm"&gt;#include &amp;quot;bytetest.h&amp;quot;&lt;/span&gt;
&lt;span class="cm"&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;*/&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unsafe&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ReadArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;outArray&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ArrayReadFunc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UBYTE&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;outArray&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;outArray&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WriteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inArray&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ArrayWriteFunc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UBYTE&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;inArray&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CArrayToByteSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arrayptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UBYTE&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayptr&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="nx"&gt;arrayptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ByteSliceToCArray&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arrayptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UBYTE&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayptr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UBYTE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;byteSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nx"&gt;arrayptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;carray&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ReadArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;carraybytes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CArrayToByteSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C array converted to byte slice:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carraybytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%d &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;carraybytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;gobytes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;gobytesarray&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ByteSliceToCArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gobytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gobytesarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;WriteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gobytesarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Functions &lt;cite&gt;ReadArray&lt;/cite&gt; and &lt;cite&gt;WriteArray&lt;/cite&gt; are just wrapper to the calls
to C counter parts &lt;cite&gt;ArrayReadFunc&lt;/cite&gt; and &lt;cite&gt;ArrayWriteFunc&lt;/cite&gt;. &lt;cite&gt;ReadArray&lt;/cite&gt;
returns &lt;cite&gt;unsafe.Pointer&lt;/cite&gt; which is allocated C array and should be
freed by caller. &lt;cite&gt;WriteArray&lt;/cite&gt; takes &lt;cite&gt;unsafe.Pointer&lt;/cite&gt; which is pointing
to memory location containing C array.&lt;/p&gt;
&lt;p&gt;Now the functions of interest are &lt;cite&gt;CArrayToByteSlice&lt;/cite&gt; and
&lt;cite&gt;ByteSliceToCArray&lt;/cite&gt;. It should be pretty clear from the above code to
understand what is happening in these functions. Still I will just put
explain them briefly.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;ByteSliceToCArray&lt;/cite&gt; allocates a C array using &lt;cite&gt;calloc&lt;/cite&gt; from C standard
library. It then creates a &lt;cite&gt;uintptr&lt;/cite&gt;, a pointer type in Go which is
used to dereference the each memory location and store bytes from the
input byte slice in them.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;CArrayToByteSlice&lt;/cite&gt; on other hands creates a &lt;cite&gt;uintptr&lt;/cite&gt; type by casting
input unsafe.Pointer type and then uses this pointer type to
dereference values from memoy and store it in byte slice with suitable
casting.&lt;/p&gt;
&lt;p&gt;So lets build the code and run it and see the output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
C array converted to byte slice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Byte slice array received from Go:
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
&lt;/pre&gt;
&lt;p&gt;So yes it actually works and values are moving across C and Go. This
solves first problem in hand next is converting arbitrary Go types
into byte slices.&lt;/p&gt;
&lt;p&gt;There are many cases where we would like to convert an arbitrary Go
types like (int, float) into bytes. One such use case I found was when
writing a TCP client for communicating with a Server written using C
speaking custom protocol. Here I'm just going to show how to convert
types like float, int to byte slice, I've not tried converting
structures but it is certainly possible.&lt;/p&gt;
&lt;p&gt;Below is the function which can convert int32,float32 into byte slice
it can also be extended for other types.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CopyValueToByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uintptr&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="kt"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Unsupported type: %T\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function is generic which can take various types of value. First
we will use Go's type assertion to determine the type and creates a
&lt;cite&gt;uintptr&lt;/cite&gt; pointer for the value and allocates byte slice depending on
the size of the value as calculated using &lt;cite&gt;unsafe.Sizeof&lt;/cite&gt;. Later it
uses the pointer to dereference value from memory location and copies
each byte into byte slice. &lt;em&gt;The idea used here is every type is
represented as certain number of bytes in the memory.&lt;/em&gt;  Below is the
entire program.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fmt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unsafe&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;os&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CopyValueToByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uintptr&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="kt"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Unsupported type: %T\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;valptr&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;10.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;floatbytes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CopyValueToByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Float value as byte slice:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatbytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%x &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floatbytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;bptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatbytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bptr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floatbytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;bptr&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Byte value copied to float var: %f\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above conversion can also be achieved using &lt;cite&gt;encoding/binary&lt;/cite&gt;
package provided by Go. But &lt;a class="reference external" href="https://twitter.com/dgryski/status/441514574307921920"&gt;its been told to me&lt;/a&gt; that it
makes things pretty slow.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So goes &lt;cite&gt;unsafe.Pointer&lt;/cite&gt; is really powerful thing which allows us to
work around the Go's type system but as package documentation says
&lt;strong&gt;it should be used with care&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
PS: I'm not really sure if its recommended to use allocation
functions from C standard library, I will wait for expert gophers to
comment on that.&lt;/blockquote&gt;
&lt;/div&gt;
</content><category term="development"/><category term="golang"/><category term="go"/><category term="programming"/></entry><entry><title>Installing and Configuring NetBSD on Qemu in Debian</title><link href="https://copyninja.in/blog/netbsd-on-qemu.html" rel="alternate"/><published>2014-03-01T22:10:00+05:30</published><updated>2014-03-01T22:10:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-03-01:/blog/netbsd-on-qemu.html</id><summary type="html">&lt;p class="first last"&gt;An introduction to installing NetBSD on Qemu and enabling
networking on a Debian host.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;First step will be getting a NetBSD ISO image for installation
purpose. It can be downloaded from &lt;a class="reference external" href="http://www.netbsd.org/mirrors/torrents/#6.1.3-ports"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next step will be creating a disk image for installing NetBSD. This is
done using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt;&lt;/tt&gt; tool like below&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;qemu-img&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;raw&lt;span class="w"&gt; &lt;/span&gt;netbsd-disk.img&lt;span class="w"&gt; &lt;/span&gt;10G
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Image format used is &lt;em&gt;raw&lt;/em&gt; and size is specified as last
arugment. Tune the size as per your need.&lt;/p&gt;
&lt;p&gt;To start the installation run the following command&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;qemu-system-x86_64&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;256M&lt;span class="w"&gt; &lt;/span&gt;-hda&lt;span class="w"&gt; &lt;/span&gt;netbsd-disk.img&lt;span class="w"&gt; &lt;/span&gt;-cdrom&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;NetBSD-6.1.3-amd64.iso&lt;span class="w"&gt; &lt;/span&gt;-display&lt;span class="w"&gt; &lt;/span&gt;curses&lt;span class="w"&gt; &lt;/span&gt;-boot&lt;span class="w"&gt; &lt;/span&gt;d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;nic&lt;span class="w"&gt; &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;user
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So this is using user mode networking so you won't be able to have
internet access during installation. I couldn't figure out on how to
get network working during installation so I configured network after
installation.&lt;/p&gt;
&lt;p&gt;Once you run above command you will be given with 4 options as
follows.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;install netbsd&lt;/li&gt;
&lt;li&gt;install netbsd with ACPI disabled&lt;/li&gt;
&lt;li&gt;install netbsd with ACPI and SMP disabled&lt;/li&gt;
&lt;li&gt;drop to boot shell&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Even though I first installed using the option 1 I couldn't get it
boot after installation so had to reinstall with option 2 and it works
fine. I'm not gonna explain each step of installation here because the
installer is really simple and straight forward! I guess the NetBSD
installer is the first simplest installer I have encountered from the
day I started with Linux. Its simple but powerful and gets job done
very easily, and I didn't read manual for installation before using
it.&lt;/p&gt;
&lt;div class="section" id="enabling-networking"&gt;
&lt;h2&gt;Enabling Networking&lt;/h2&gt;
&lt;p&gt;This section involves mixture of configuration in Debian host and
inside NetBSD to get the network working. The wiki page of Debian on
&lt;a class="reference external" href="https://wiki.debian.org/QEMU#Networking"&gt;Qemu&lt;/a&gt;. helped me here.&lt;/p&gt;
&lt;p&gt;To share the network with Qemu there are 2 possiblities&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Bridged networking between host and guest using &lt;em&gt;bridge-utils&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Using VDE &lt;em&gt;(Virtual Distributed Ethernet)&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The option 1 which is explained in wiki linked above didn't work for
me as I use CDC Ether based datacard for connecting to Internet which
gets detected as &lt;em&gt;eth1&lt;/em&gt; on my machine. When bridging happens between
&lt;em&gt;tap0&lt;/em&gt; and &lt;em&gt;eth1&lt;/em&gt; I end up loosing Internet on my host machine. So I
selected to use VDE instead.&lt;/p&gt;
&lt;p&gt;First install packages &lt;em&gt;vde2&lt;/em&gt; and &lt;em&gt;uml-utilities&lt;/em&gt; once done edit the
&lt;em&gt;/etc/network/interfaces&lt;/em&gt; file and add following lines:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
auto vdetap
iface vdetap inet static
   address 192.168.2.1
   netmask 255.255.255.0
   vde2-switch -t vdetap
&lt;/pre&gt;
&lt;p&gt;We can use &lt;em&gt;dnsmasq&lt;/em&gt; as a DHCP server for the &lt;em&gt;vdetap&lt;/em&gt; interface, but
I'm not gonna explain the configuration of &lt;em&gt;dnsmasq&lt;/em&gt; here. Run the
below command to get vdetap up&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="go"&gt;modprobe tun&lt;/span&gt;
&lt;span class="go"&gt;ifup vdetap&lt;/span&gt;
&lt;span class="go"&gt;/etc/init.d/dnsmasq restart&lt;/span&gt;
&lt;span class="go"&gt;newgrp vde2-net # run as user starting Qemu VM&amp;#39;s&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I couldn't get successful output for &lt;em&gt;newgrp&lt;/em&gt; command, I was getting
some &lt;tt class="docutils literal"&gt;crypt: Invalid argument&lt;/tt&gt; output. But I could still get
network working on NetBSD so I considered to ignore that for now.&lt;/p&gt;
&lt;p&gt;Now start the NetBSD qemu instance running using following command&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;qemu-system-x86_64&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;256M&lt;span class="w"&gt; &lt;/span&gt;-hda&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;/mnt/kailash/BSDWorld/netbsd-disk.img&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;nic&lt;span class="w"&gt; &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;vde,sock&lt;span class="o"&gt;=&lt;/span&gt;/var/run/vde2/vdetap.ctl&lt;span class="w"&gt; &lt;/span&gt;-display&lt;span class="w"&gt; &lt;/span&gt;curses
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once the system is up login using &lt;em&gt;root&lt;/em&gt; user, NetBSD will warn you
for this and suggest to create another user but for now ignore
it. To find the network interface in NetBSD just run the usual
&lt;em&gt;ifconfig&lt;/em&gt; command. In my case interface is named &lt;em&gt;wm0&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;First step will be configuring the IP address for your interface and
setting up the gateway route. Run the below command for this purpose&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;# &lt;/span&gt;ifconfig&lt;span class="w"&gt; &lt;/span&gt;wm0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.2.2&lt;span class="w"&gt; &lt;/span&gt;netmask&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;.255.255.0
&lt;span class="gp"&gt;# &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.2.1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that I added gateway as IP address of vdetap on my host
machine. Now try pinging the host and even you can try ssh to host
system.&lt;/p&gt;
&lt;p&gt;But note that this is not persistent over the reboots and for some
reason I didn't yet figure out how to make NetBSD get address over
DHCP from my host machine. I will update once I figure it out. Now to
make the connection address persistent over reboots you need to create
a file by name &lt;em&gt;/etc/ifconfg.&amp;lt;interface&amp;gt;&lt;/em&gt;. Replace &lt;em&gt;interface&lt;/em&gt; with a
proper interface on your running NetBSD. In my case this file is
&lt;em&gt;/etc/ifconfig.wm0&lt;/em&gt; and has following content.:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
192.168.2.2 netmask 0xffffff00 media autoselect
&lt;/pre&gt;
&lt;p&gt;Set the DNS server as host by adding file &lt;em&gt;/etc/resolv.conf&lt;/em&gt; with
following content.:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
nameserver 192.168.2.1
&lt;/pre&gt;
&lt;p&gt;After this you need to do NAT/masquerading using iptables. Just copy
following script to a file and execute it as root&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="c1"&gt;# Restart the dnsmasq&lt;/span&gt;
/etc/init.d/dnsmasq&lt;span class="w"&gt; &lt;/span&gt;restart

&lt;span class="c1"&gt;# Set nat rules in iptables&lt;/span&gt;
iptables&lt;span class="w"&gt; &lt;/span&gt;--flush
iptables&lt;span class="w"&gt; &lt;/span&gt;--table&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;--flush
iptables&lt;span class="w"&gt; &lt;/span&gt;--delete-chain
iptables&lt;span class="w"&gt; &lt;/span&gt;--table&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;--delete-chain

&lt;span class="c1"&gt;# Replace accordingly usb0 with ppp0 for 3G&lt;/span&gt;
iptables&lt;span class="w"&gt; &lt;/span&gt;--table&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;--append&lt;span class="w"&gt; &lt;/span&gt;POSTROUTING&lt;span class="w"&gt; &lt;/span&gt;--out-interface&lt;span class="w"&gt; &lt;/span&gt;eth1&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;MASQUERADE
iptables&lt;span class="w"&gt; &lt;/span&gt;--append&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;--in-interface&lt;span class="w"&gt; &lt;/span&gt;vdetap&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT

&lt;span class="c1"&gt;# Enable IP forwarding in Kernel&lt;/span&gt;
sysctl&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;net.ipv4.ip_forward&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With the above setup you will be able to get DNS resolution even after
you reboot the Qemu instance but Internet connection will not work
untill you run the &lt;tt class="docutils literal"&gt;route&lt;/tt&gt; command I mentioned above. I still didn't
figure out how to persist route but I will update it here once I
figure it out.&lt;/p&gt;
&lt;blockquote&gt;
Note that you won't be able to SSH as root to NetBSD (may be its
configured to not allow by default), so you would need to create a
normal user before trying to SSH from host to guest. Also make sure
you add the user to &lt;em&gt;wheel&lt;/em&gt; group to allow him execute su command.&lt;/blockquote&gt;
&lt;p&gt;So now I've NetBSD running on my laptop with mere 256M ram and its
amazingly fast even at such low RAM. I've created a new user and can
SSH into it from host machine and use it just like I use a
server!. I will put up the notes of my BSD adventure here
periodically.&lt;/p&gt;
&lt;p&gt;The feeling of using a BSD is amazing :-)&lt;/p&gt;
&lt;blockquote&gt;
&lt;strong&gt;Update&lt;/strong&gt;: I forgot to add masquerading step, I've added it
now.&lt;/blockquote&gt;
&lt;/div&gt;
</content><category term="bsd"/><category term="debian"/><category term="netbsd"/><category term="qemu"/><category term="vde"/><category term="networking"/></entry><entry><title>Gzipped response for CSS/JS with Apache and mod_uwsgi</title><link href="https://copyninja.in/blog/comressed-response.html" rel="alternate"/><published>2014-03-01T09:00:00+05:30</published><updated>2014-03-01T09:00:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-03-01:/blog/comressed-response.html</id><summary type="html">&lt;p class="first last"&gt;Apache started sending completely gziped response when using
with mod_uwsgi plugin. Post tries to find the problem cause.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;So it may sound normal to receive compressed response for CSS/JS file
from Apache2 but what I faced is completely different behavior, here I
saw not just body of response but also header are getting compressed
and send to browser and browser was unable to interpret the response
there by leading page rendered without CSS and JS.&lt;/p&gt;
&lt;p&gt;That was long story short, so let me explain in detail the case and
what I found out.&lt;/p&gt;
&lt;p&gt;I have &lt;a class="reference external" href="http://silpa.org.in"&gt;hosted&lt;/a&gt; &lt;a class="reference external" href="https://github.com/Project-SILPA/Silpa-Flask"&gt;SILPA&lt;/a&gt; on my VPS using
uWSGI. I had used till date using &lt;em&gt;libapache2-mod-proxy-uwsgi&lt;/em&gt; plugin
for which uWSGI should be using network socket and in Apache2 config I
need &lt;em&gt;ProxyPass&lt;/em&gt; directive pointing to &lt;em&gt;uwsgi://host:port&lt;/em&gt; and
everything used to work out of box. There is a drawback for using
network socket in uWSGI that is limited amount of ports (65535) and
possible clash with other services if we use wrong port number,
additionally network sockets will be slower compared to the file
socket so yesterday I thought of changing it to file socket and
removed &lt;em&gt;socket&lt;/em&gt; directive in the ini file for uWSGI application
container for SILPA and here is where all problems started. My updated
configuration can be seen in our &lt;a class="reference external" href="http://silpa.readthedocs.org/en/latest/installation.html#hosting-the-silpa-on-webserver"&gt;documentation page&lt;/a&gt;
that is if you are interested to look my configuration file :-).&lt;/p&gt;
&lt;div class="section" id="problem-reporting"&gt;
&lt;h2&gt;Problem Reporting&lt;/h2&gt;
&lt;p&gt;We got selected to Gsoc again this year and we have lot of students
jumping in our channel &lt;em&gt;#silpa&lt;/em&gt; on &lt;em&gt;irc.freenode.net&lt;/em&gt; and yesterday
night some students reported they are facing &lt;em&gt;500 internal server
error&lt;/em&gt; and subsequently others mentioned there is no theme being
rendered. I checked and found everything was fine for me only to
notice that my browser was using cached content, and when I clear
cache there I go everything vanished, no theme no css no javascript
just plain html!!!.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="investigation"&gt;
&lt;h2&gt;Investigation&lt;/h2&gt;
&lt;p&gt;So I thought I should investigate this and fired up &lt;em&gt;firebug&lt;/em&gt; on my
iceweasel to observe the network traffic. And below is what I observed
in firebug network console!.&lt;/p&gt;
&lt;img alt="No response headers" class="align-center" src="https://copyninja.in/images/no-response-css.png" /&gt;
&lt;p&gt;So you can see no response header in the above image but there is a
response and below how is response content visible on firebug.&lt;/p&gt;
&lt;img alt="gzipped response" class="align-center" src="https://copyninja.in/images/response-content.png" /&gt;
&lt;p&gt;Still weird part was when using wget/curl directly to get the CSS I
was getting correct reply and the file, which is puzzling.&lt;/p&gt;
&lt;p&gt;So I went ahead opened the CSS url directly using browser and saved
the resulting file. When I used &lt;tt class="docutils literal"&gt;file&lt;/tt&gt; command on it, output
suggested the saved file in gzip compressed!. I went ahead
uncompressed it and opened the file and inside it I found response
header and the response body! So what just happened? Did apache some
how manage to compress entire respone not just response body?&lt;/p&gt;
&lt;p&gt;The more puzzling question was why did it work when I was using
&lt;em&gt;mod_proxy_uwsgi&lt;/em&gt; and failed when I switched to &lt;em&gt;mod_uwsgi&lt;/em&gt;. I had no
clue at this point why this behavior is coming up.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="possible-solution"&gt;
&lt;h2&gt;Possible Solution&lt;/h2&gt;
&lt;p&gt;I was still not sure how to resolve this, and started searching in the
network but nothing was coming up in search result which can explain
me this. And finally I stumbled on a link which is &lt;a class="reference external" href="http://bit.ly/1eJdQe8"&gt;totally unrelated&lt;/a&gt; but I saw the word &lt;em&gt;mod_deflate&lt;/em&gt; in the
content and wandered on my system to see if its enabled. Yes
mod_deflate was enabled I just opened the conf file and saw
following.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;IfModule&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mod_deflate.c&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c"&gt;# these are known to be safe with MSIE 6&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;AddOutputFilterByType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DEFLATE&lt;span class="w"&gt; &lt;/span&gt;text/html&lt;span class="w"&gt; &lt;/span&gt;text/plain&lt;span class="w"&gt; &lt;/span&gt;text/xml

&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c"&gt;# everything else may cause problems with MSIE 6&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;AddOutputFilterByType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DEFLATE&lt;span class="w"&gt; &lt;/span&gt;text/css
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;AddOutputFilterByType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DEFLATE&lt;span class="w"&gt; &lt;/span&gt;application/x-javascript&lt;span class="w"&gt; &lt;/span&gt;application/javascript&lt;span class="w"&gt; &lt;/span&gt;application/ecmascript
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;AddOutputFilterByType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DEFLATE&lt;span class="w"&gt; &lt;/span&gt;application/rss+xml
&lt;span class="nt"&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Interesting so it suggests to compress css, javascript files etc. So I
thought possibly its compressing the result of &lt;em&gt;mod_uwsgi&lt;/em&gt;, yeah possibly so
why not try disabling &lt;em&gt;mod_deflate&lt;/em&gt; and check if it works well and
good if not I'm not gonna loose anything. So I disabled &lt;em&gt;mod_deflate&lt;/em&gt;
and voila! Everything is working fine!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-might-be-the-reason-for-this-behavior"&gt;
&lt;h2&gt;What might be the reason for this behavior?&lt;/h2&gt;
&lt;p&gt;Well I'm not exactly sure but here is my assumption. The whole
behavior depends on internal implementation of &lt;strong&gt;mod_uwsgi&lt;/strong&gt; and
&lt;strong&gt;mod_proxy_uwsgi&lt;/strong&gt; module. To confirm this I switched back to use
&lt;strong&gt;mod_proxy_uwsgi&lt;/strong&gt; module and enabled &lt;strong&gt;mod_deflate&lt;/strong&gt; and observed
request response in &lt;strong&gt;Firebug&lt;/strong&gt; network console and below is what I
observed.&lt;/p&gt;
&lt;img alt="Response with mod_proxy_uwsgi" class="align-center" src="https://copyninja.in/images/response-content-uwsgi-proxy.png" /&gt;
&lt;p&gt;So response is still gziped but this time only response body was
gziped and Content-Encoding field was set properly which makes browser
to properly uncompress the response body and use it.&lt;/p&gt;
&lt;p&gt;So it seems like there is a difference between mod_uwsgi and
mod_proxy_uwsgi implementation. mod_uwsgi was sending the response
along with response headers which was compressed by mod_deflate there
by rendering browser helpless to interpret the response. But
mod_proxy_uwsgi seems to be only sending the response content without
response body and this content was later compressed by mod_deflate and
proper response headers were set by apache before sending it to
browser.&lt;/p&gt;
&lt;p&gt;So now whose fault is this? Is it the bug in mod_uwsgi or, mod_deflate
not being able to exclude response headers from compression? I've no
clue! If you have a clue and you want to share it with me, please
consider writing to me over email. My details are available in
&lt;a class="reference external" href="http://copyninja.info/contact"&gt;Contacts&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="development"/><category term="python"/><category term="apache2"/><category term="mod_uwsgi"/><category term="mod_deflate"/></entry><entry><title>First experience of driving in Bangalore</title><link href="https://copyninja.in/blog/driving-in-bangalore.html" rel="alternate"/><published>2014-02-22T17:24:00+05:30</published><updated>2014-02-22T17:24:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-02-22:/blog/driving-in-bangalore.html</id><summary type="html">&lt;p class="first last"&gt;Experience of driving 2 wheeler first time in Bangalore&lt;/p&gt;
</summary><content type="html">&lt;p&gt;So finally I did it, I managed to ride the 2-wheeler in Bangalore
roads!. Officially I've got a license to drive 2 and 4 wheelers back
in 2011 but I was never confident enough to ride the vehicle on road
and in traffic. Partially this is because I don't own a vehicle and
I've never practiced driving, and partially because of road and
traffic conditions in India I was bit afraid to do so.&lt;/p&gt;
&lt;p&gt;So today morning my roommate and me planned to go to temple in the
early morning. We got up at 530 in the morning and we were ready to
drive to Mahalaxmi Layout at 615. Since during this time traffic is
very less I asked my roommate shall I drive and he agreed!.&lt;/p&gt;
&lt;p&gt;So I drove the bike from &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Malleshwaram"&gt;Malleshwaram&lt;/a&gt; to &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Mahalakshmi_Layout"&gt;Mahalaxmi Layout&lt;/a&gt; and it was fun. I
did had hick up in uphill driving as my mind was not co-ordinating
well with breaks and gear. I did have hickups in first gear too but I
guess this will be alright once I get hold of things.&lt;/p&gt;
&lt;p&gt;I'm still not having enough confidence to drive during the peak hours
because people are not at all following traffic rules. They just
change the lane without any hints or just come to middle of road from
side roads without looking at other side to see if there is a vehicle
is coming from other side of the road (yes they don't have courtesy to
wait). And finally they can shout at persons who is actually following
rules. In general very less people have traffic discipline in
India. But I will adapt to this once I start driving so I'm now all
set to get my 2 wheeler soon and ride on!&lt;/p&gt;
</content><category term="vehicle"/><category term="driving"/><category term="vehicle"/><category term="traffic"/><category term="confidence"/></entry><entry><title>Kontalk FLOSS alternative for Whatsapp and Co.</title><link href="https://copyninja.in/blog/kontalk-messaging.html" rel="alternate"/><published>2014-02-21T19:51:00+05:30</published><updated>2014-02-21T19:51:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-02-21:/blog/kontalk-messaging.html</id><summary type="html">&lt;p class="first last"&gt;FLOSS alternative for Whatsapp.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;So &lt;em&gt;Whatsapp&lt;/em&gt; has been acquired by Facebook and this news is still hot
and people are discussing it all over the twitterverse. So I took this
opportunity to stop using &lt;em&gt;Whatsapp&lt;/em&gt; and removed it from my
phone. Possibly I could have deleted my account but who cares.&lt;/p&gt;
&lt;p&gt;Anyway I've been searching for a secure and FLOSS alternative for
&lt;em&gt;Whatsapp&lt;/em&gt; for quite some time now, few days ago I found about
&lt;em&gt;Telegram&lt;/em&gt; but after reading &lt;a class="reference external" href="http://blog.tincho.org/posts/Telegram/"&gt;post&lt;/a&gt; by Tincho on planet Debian,
I decided not to use it.  Recently while going through the talk list
for fossmeet.in I found link for &lt;a class="reference external" href="http://kontalk.org"&gt;Kontalk&lt;/a&gt; in a
privacy awareness talk &lt;a class="reference external" href="http://funnel.fossmeet.in/2014/61-i-have-nothing-to-hide-i-dont-care-about-privacy"&gt;proposal&lt;/a&gt;
by &lt;a class="reference external" href="http://qa.debian.org/developer.php?login=praveen"&gt;Praveen&lt;/a&gt; and
thought I should give it a try.  So below is my first feelings about
&lt;em&gt;Kontalk&lt;/em&gt;.&lt;/p&gt;
&lt;div class="section" id="installation-and-activation"&gt;
&lt;h2&gt;Installation and Activation&lt;/h2&gt;
&lt;p&gt;Kontalk can be installed from &lt;a class="reference external" href="https://play.google.com/store/apps/details?id=org.kontalk"&gt;playstore&lt;/a&gt; for
verification purpose it requests your phone number and country code
and request for verification. This should send a SMS with a code which
should be entered in the text box given and app is ready to use. There
is also a possibility to use pre-existing verification code (if you
got one from developer directly, read below for details).&lt;/p&gt;
&lt;p&gt;I did see some glitches like I never got the SMS delivered to my phone
after 2 attempts and a days wait. Then I went ahead and reported a
&lt;a class="reference external" href="https://code.google.com/p/kontalk/issues/detail?id=179"&gt;bug&lt;/a&gt; and
the main developer was quick to respond. After a discussion it was
noticed that SMS was blocked by spam filters. He also mentioned its
tough to get SMS delivered to India. He was kind enough to provide me
with a verification code and I used the &lt;em&gt;Use existing code&lt;/em&gt; option to
enter it and get &lt;em&gt;Kontalk&lt;/em&gt; activated.&lt;/p&gt;
&lt;p&gt;The SMS delivery inconsistency is still present for India (and may be
other nations too) some people get code immidiately others may be
after couple of days and some might not. Upstream is already working
on a possible &lt;a class="reference external" href="https://code.google.com/p/kontalk/issues/detail?id=141"&gt;workaround&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="user-experience"&gt;
&lt;h2&gt;User Experience&lt;/h2&gt;
&lt;p&gt;Now coming to usage part, the UI is neat and clean, I won't say super
polished as &lt;em&gt;Whatsapp&lt;/em&gt; or other popular apps but its really &lt;em&gt;neat&lt;/em&gt; and
easy to use. Some points which I like are&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Ability to hide presence, so others won't know you are online or
offline. (unlike &lt;em&gt;Whatsapp&lt;/em&gt; which advertises last seen)&lt;/li&gt;
&lt;li&gt;Encrypted messages and ability to optin or optout.&lt;/li&gt;
&lt;li&gt;Encrypted status messages! Only user with your phone number can see
your status. (Cool isn't it).&lt;/li&gt;
&lt;li&gt;Manually requesting to find contacts who already uses
kontalk!. Right it doesn't read your contact list without your
permission you need to refresh to check who in your contacts is
using Kontalk.&lt;/li&gt;
&lt;li&gt;Attach and smiley options in the top right corner of Chat window
which allows easy accessing unlike keyboard - smiley switching of
&lt;em&gt;Whatsapp&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;No automatic download of media contents which is shared. Yes by
default it doesn't download any picture or video automatically if
you want to see something click on it and select download.&lt;/li&gt;
&lt;li&gt;Running your own server for Kontalk! Now thats something which is
interesting for people who doesn't want to host their data on some
other peoples infrastructure. Code for server is available at
&lt;a class="reference external" href="https://code.google.com/p/kontalk/source/browse?repo=xmppserver"&gt;xmppserver&lt;/a&gt;
repo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But there are some rough edges also but I'm sure this can be
improved. But some points which I noticed are&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Contact name disappears and only number is displayed. This is
something which happened with one of my contact so I'm not really
sure its a bug.&lt;/li&gt;
&lt;li&gt;My friend noticed all his existing contacts suddenly vanished when
he refreshed contacts list. Again this is possible bugs and we are
considering reporting it upstream.&lt;/li&gt;
&lt;li&gt;No group chats yet. I don't see a option to do that yet.&lt;/li&gt;
&lt;li&gt;Attachment at the moment is restricted only to pictures (and video?
never tried) and uploading takes quite sometime and sometime hangs
forever.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I'm considering forwarding these to upstream and help them by
providing enough data so these can be fixed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="technical-side"&gt;
&lt;h2&gt;Technical Side&lt;/h2&gt;
&lt;p&gt;All code for client server and protocol specs are available under
GPL-v3 at the &lt;a class="reference external" href="https://code.google.com/p/kontalk"&gt;Kontalk project&lt;/a&gt;
site. Server software is written in Python and I guess uses XMPP (but
I've not cross verified). Server also uses MySQL as database. These
can be hosted on our own servers but possibly needs more than that
like SMS sending options etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In my views &lt;em&gt;Kontalk&lt;/em&gt; can become a great alternative for &lt;em&gt;Whatsapp&lt;/em&gt;
and co from Free Software world and I encourage every one to give it a
try which will be the first step to help improving it.&lt;/p&gt;
&lt;blockquote&gt;
Disclaimer: I'm not a privacy or security expert so whatever I shared
above are what I noticed and experts may see something different than
this. In any case I welcome comments and suggestions.&lt;/blockquote&gt;
&lt;/div&gt;
</content><category term="misc"/><category term="smartphone"/><category term="messaging"/><category term="whatsapp"/><category term="foss"/></entry><entry><title>Friendica instance on my VPS is down</title><link href="https://copyninja.in/blog/friendica-instance-down.html" rel="alternate"/><published>2014-02-08T20:31:00+05:30</published><updated>2014-02-08T20:31:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-02-08:/blog/friendica-instance-down.html</id><summary type="html">&lt;p class="first last"&gt;Friendica instance on my vps went down.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I started running &lt;a class="reference external" href="http://friendica.com"&gt;Friendica&lt;/a&gt; instance on my
VPS. With help of &lt;a class="reference external" href="http://dr.jones.dk"&gt;Jonas Smedegaard&lt;/a&gt; I managed
to run Friendica in a uWSGI container. The site was running at
&lt;em&gt;samsargika.copyninja.info&lt;/em&gt; and is no longer accessible.&lt;/p&gt;
&lt;p&gt;Since VPS itself was running Debian Wheezy I couldn't run uWSGI with
PHP support on it. &lt;em&gt;(support for PHP in uWSGI landed after
Wheezy)&lt;/em&gt;. But Jonas was kind enough for me to provide a backported
version.&lt;/p&gt;
&lt;p&gt;Recently Wheezy got a security update for PHP and thats where all the
problem started. The backported &lt;em&gt;uwsgi-plugin-php&lt;/em&gt; was not recompiled
to use security updated PHP and I couldn't upgrade the things. After
few days I noticed first freeze on my VPS and I had to reboot the VPS
to get it online again. The fact I noticed was uWSGI being killed due
to a OOM in syslog but I didn't explore much and consulted Jonas to
get a updated uWSGI. But that didn't happen as Jonas himself is facing
some problem with uWSGI builds. While again checking with aptitude for
upgrade I accidentally confirmed removal of &lt;em&gt;uwsgi-plugin-php&lt;/em&gt; for
getting security updates :-/. But nothing happened to my running
service as upgrade of libs in Debian doesn't cause the restart of all
services which are using that lib &lt;em&gt;(desired effect is restart of
service but I don't know the side affects involved)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Second freeze happened yesterday and on the reboot &lt;em&gt;uwsgi-plugin-php&lt;/em&gt;
was missing there by taking my Friendica instance down. More closer
investigation showed the same OOM but this time I noticed each OOM
occurred just after cronjob was running &lt;em&gt;poller.php&lt;/em&gt; a script which is
actually causing all federation in Friendica. So it was clear there is
something wrong either in &lt;em&gt;poller.php&lt;/em&gt; or in my setup which was making
it eat memory and freeze my VPS.&lt;/p&gt;
&lt;p&gt;But I also found some stupidity I did during configuration which Jonas
also pointed me out.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;em&gt;Installing cronjob inside crontab rather than cron.d&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Installing poller.php crontab for root user :-/&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I basically violated the basic rule by running a unsafe script as root
user, good that script didn't do some crazy stuff. So even though my
instance went down I learnt my lessons&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;em&gt;Don't ever ever ever run a unsafe script as root that too through cron&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Sandbox the unsafe script so it can be killed on time rather than
it taking the whole system down.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;PHP is not really secure, if it was secure there wouldn't be
security updates and atleast my site would be still running :-D&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So I now need to wait till Jonas get me new shiny backported uWSGI
linked against new PHP on Wheezy and till that time I need to explore
on how I can sandbox the poller.php script.&lt;/p&gt;
</content><category term="misc"/><category term="friendica"/><category term="sysadmin"/><category term="php"/><category term="debian"/><category term="sandboxing"/></entry><entry><title>Moving weblog from Jekyll to Pelican</title><link href="https://copyninja.in/blog/blog-move.html" rel="alternate"/><published>2014-02-02T08:55:00+05:30</published><updated>2014-02-02T08:55:00+05:30</updated><author><name>copyninja</name></author><id>tag:copyninja.in,2014-02-02:/blog/blog-move.html</id><summary type="html">&lt;p class="first last"&gt;Re-creating blog using Pelican&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Its been a while and I was not actively blogging. I wanted to start
blogging again but I was for some reason not happy with &lt;em&gt;Jekyll&lt;/em&gt;
static site generator which was powering my previous site. So I took
this chance to explore other static site generators and redesign my
blog.&lt;/p&gt;
&lt;p&gt;I explored a bit of Pelican, Nikola and Frog. I didn't feel
comfortable with &lt;em&gt;Nikola&lt;/em&gt;. &lt;em&gt;Frog&lt;/em&gt; is a static site generator written
using &lt;a class="reference external" href="http://racket-lang.org/"&gt;*Racket*&lt;/a&gt; and since I'm learning
Scheme using racket I was leaning towards using it but at the last
moment I decided to settle with &lt;em&gt;Pelican&lt;/em&gt;. The main reason for not
using &lt;em&gt;Frog&lt;/em&gt; was that I just wanted to get my site up rather than
waiting for me to complete learning racket and use Frog.&lt;/p&gt;
&lt;p&gt;My feeling about Pelican is that its a nice tool and is simple and
gives all basic things like generating RSS/ATOM feeds and nice theming
support. In case of Jekyll I had to write custom page for creating RSS
feed and had pain in creating my first theme (yeah I'm not a
designer). But now things might have changed in Jekyll land but anyway
I don't care anymore.&lt;/p&gt;
&lt;p&gt;New design uses &lt;a class="reference external" href="https://github.com/DandyDev/pelican-bootstrap3"&gt;pelican-bootstrap3&lt;/a&gt; theme and there is
no comment facility available. If you want to comment or suggesting
things on my post consider writing mail to me :-).&lt;/p&gt;
&lt;p&gt;So what happened to older entries? Moving the old entries from Jekyll
format to Pelican was real PITA so I just renamed my old site to
&lt;a class="reference external" href="http://blog-archive.copyninja.info"&gt;blog-archive&lt;/a&gt;. So this is a
from scratch site and will contain only new entries. So how do you
like my new blog design? :-)&lt;/p&gt;
</content><category term="misc"/><category term="jekyll"/><category term="pelican"/><category term="blog"/></entry></feed>