Category Archives: Tech

VoidLinux in FreeBSD Jail; with init

Two important things happened this week for me.

First, Faraz asked me if I can rename my Jail manager to something other than Jailio because he got that domain for his Jailer manager already. So I named it

Second, I was able to run a complete Linux system using Jailer. While the repo for Jailer is not released yet (we are auditing for possible security issues), I would like to share how I was able to run VoidLinux in a Jail.

Since Jailer is not announced yet, I will give the examples using jail.conf, as most people either are or should be familiar with its concepts.

I went with VoidLinux because I am able to run the init process without its need to be running as PID1.

Let’s start, shall we?

First, ZFS dataset for our jail!

zfs create zroot/jails/voidlinux

Next we need to fetch the base system of VoidLinux. Luckily they do provide it on their website.

fetch https://alpha.de.repo.voidlinux.org/live/current/void-x86_64-ROOTFS-20210218.tar.xz

Now we can extract this into our dataset

tar xf void-x86_64-ROOTFS-20210218.tar.xz -C /usr/local/jails/voidlinux/

You might get an error that ./usr/bin/iputils-ping: Cannot restore extended attributes: security.capability, which is fine, I think?

If you are on FreeBSD 12.2-RELEASE or later, now you need to enable the Linuxulator.

service linux enable; service linux start

Now you can at least chroot into the system.

chroot /usr/local/jails/voidlinux/ /bin/bash

If everything is fine until now, perfect.

Now we need to add a root user into the system.

root@host:~ # cd /usr/local/jails/voidlinux/etc/
root@host:/usr/local/jails/voidlinux/etc # echo "root::0:0::0:0:Charlie &:/root:/bin/bash" > master.passwd
root@host:/usr/local/jails/voidlinux/etc # pwd_mkdb -d ./ -p master.passwd
pwd_mkdb: warning, unknown root shell

Execute the rest of the commands in Void.

root@host:~ # chroot /usr/local/jails/voidlinux/ /bin/bash
bash-5.1# cd /etc/
bash-5.1# pwconv 
bash-5.1# grpconv 
bash-5.1# passwd 
New password: 
Retype new password: 
passwd: password updated successfully
bash-5.1# exit

If all went fine, then the system is ready to be run as a Jail!

First we need to make an fstab for the system.

Create a file at /usr/local/jails/voidlinux/etc/fstab.pre and insert the following inside

devfs       /usr/local/jails/voidlinux/dev      devfs           rw                      0   0
tmpfs       /usr/local/jails/voidlinux/dev/shm  tmpfs           rw,size=1g,mode=1777    0   0
fdescfs     /usr/local/jails/voidlinux/dev/fd   fdescfs         rw,linrdlnk             0   0
linprocfs   /usr/local/jails/voidlinux/proc     linprocfs       rw                      0   0
linsysfs    /usr/local/jails/voidlinux/sys      linsysfs        rw                      0   0
/tmp        /usr/local/jails/voidlinux/tmp      nullfs          rw                      0   0

Next, let’s create a loopback interface for networking. Oh yes, VNET is not supported yet, but I’m working on a patch 🙂

ifconfig lo1 create
ifconfig lo1 inet 10.10.0.1/24 up # sorry, 10.0.0.0/24 was unavailable :P

Okay, time to create our Jail conf!

exec.clean;
allow.raw_sockets;
mount.devfs;

voidlinux {
    $id     = "1";
    $ipaddr = "10.10.0.42";
    $mask   = "255.255.255.0";
    $domain = "srv0.bsd.am";
    devfs_ruleset  = 4;
    allow.mount;
    allow.mount.devfs;
    mount.fstab = "${path}/etc/fstab.pre";

    exec.start     = "/bin/sh /etc/runit/2 &";
    exec.stop      = "/bin/sh /etc/runit/3";


    ip4.addr      = "${ipaddr}";
    interface     = "lo1";
    host.hostname = "${name}.${domain}";
    path = "/usr/local/jails/voidlinux";
    exec.consolelog = "/var/log/jail-${name}.log";
    persist;
    allow.socket_af;
}

Let’s check?

# jls
   JID  IP Address      Hostname                      Path
     1  192.168.0.42    voidlinux.srv0.bsd.am         /usr/local/jails/voidlinux

And the process tree?

# ps auxd -J voidlinux
USER   PID %CPU %MEM  VSZ  RSS TT  STAT STARTED    TIME COMMAND
root 35182  0.0  0.1 2320 1428  -  SsJ  21:09   0:00.12 runsvdir -P /run/runit/runsvdir/current log: ot set SO_PASSCRED: Protocol not available\ncould not set SO_PASSCRED: Protocol
root 35190  0.0  0.1 2168 1376  -  SsJ  21:09   0:00.02 - runsv agetty-tty6
root 35397  0.0  0.1 2412 1704  -  SsJ  21:10   0:00.00 `-- agetty tty6 38400 linux
root 35191  0.0  0.1 2168 1376  -  SsJ  21:09   0:00.02 - runsv agetty-tty1
root 35396  0.0  0.1 2412 1704  -  SsJ  21:10   0:00.00 `-- agetty --noclear tty1 38400 linux
root 35192  0.0  0.1 2168 1376  -  SsJ  21:09   0:00.02 - runsv agetty-tty5
root 35398  0.0  0.1 2412 1704  -  SsJ  21:10   0:00.01 `-- agetty tty5 38400 linux
root 35193  0.0  0.1 2168 1376  -  SsJ  21:09   0:00.02 - runsv agetty-tty2
root 35393  0.0  0.1 2412 1704  -  SsJ  21:10   0:00.00 `-- agetty tty2 38400 linux
root 35194  0.0  0.1 2168 1396  -  RsJ  21:09   0:00.12 - runsv udevd
root 35195  0.0  0.1 2168 1376  -  SsJ  21:09   0:00.02 - runsv agetty-tty3
root 35394  0.0  0.1 2412 1704  -  SsJ  21:10   0:00.00 `-- agetty tty3 38400 linux
root 35196  0.0  0.1 2168 1376  -  SsJ  21:09   0:00.02 - runsv agetty-tty4
root 35390  0.0  0.1 2412 1704  -  SsJ  21:10   0:00.00 `-- agetty tty4 38400 linux

You may jexec now 🙂

# jexec voidlinux /bin/bash
bash-5.1# uname -a
Linux voidlinux.srv0.bsd.am 3.2.0 FreeBSD 12.2-RELEASE-p6 GENERIC x86_64 GNU/Linux

Let’s check networking?

bash-5.1# ping -c 1 10.10.0.1
ping: WARNING: setsockopt(ICMP_FILTER): Protocol not available
PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data.
64 bytes from 10.10.0.1: icmp_seq=1 ttl=64 time=0.069 ms

--- 10.10.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.069/0.069/0.069/0.000 ms

There you go! Well, things that are related to netlink might not work, but other than that it’s okay.

I did have some problems while installing packages, something about too many levels of symbolic links. Here’s the exact output when I was trying to install the curl package

[*] Unpacking packages
libev-4.33_1: unpacking ...
ERROR: libev-4.33_1: [unpack] failed to extract file `./usr/lib/libev.so.4': Too many levels of symbolic links
ERROR: libev-4.33_1: [unpack] failed to extract files: Too many levels of symbolic links
ERROR: libev-4.33_1: [unpack] failed to unpack files from archive: Too many levels of symbolic links
Transaction failed! see above for errors.

Now, I did not find the time to fix this yet, but if you have any idea, please let me know or comment below 🙂

So, what do we have here? A Linux Jail, running VoidLinux, with init, so you can also run services, and basic networking for it.

That’s all folks…

Linux is dead, long-live Docker monoculture

Full Discloser: While reading this blog post, please put yourself in my shoes. You’ve been looking around for a simple monitoring solution, you found some. None of the some are working because you use an Operating System that is used by Apple, WhatsApp, Netflix and many more, but developers think that everyone, everywhere, runs either macOS or Linux. And they all use Docker.

A while back Rubenerd wrote that he’s not sure that UNIX won and how Linux created a monoculture of assuming everything is supposed to run on Linux.

For me, this was not much of a problem, I can run Linux binaries on FreeBSD, I even watch Netflix using Linuxulator.

But now things are on another level, WAY another level.

I have a simple monitoring setup using cron, Grafana, InfluxDB and ping. It basically pings my servers and sends me a telegram message if they are down.

I set that up years ago, but now I have more public facing infrastructure that other people use as well, such as an Armenian Lobsters instance, Jabber.am, a WriteFreely instance and more.

As a self-respecting Ops, I wanted to make a simple dashboard for my users to see the uptime status of these services as well. First, they won’t bug me asking if something is not working; they will SEE, that, SSL/TLS certificate is expired, or the network is an issue, or that the server is down.

<rant>

So I started hunting on the internet for some software that do just that.

The first one that came to my mind was Gatus. I’ve used Gatus before for one of my clients, I like it a lot. It’s simple, it does what it’s supposed to do.

As a sane person, I fetched the code from GitHub using fetch, extracted the tarball and ran make. Nothing happens. Let’s see the Makefile, shall we?

Docker executed in Make

Oh boy, if only, only, I had Docker, all my problems would be solved. First of all, let’s talk about the fact that this Makefile is used as a… script. There’s no dependencies in the targets!

Okay, let’s read that Dockerfile. Executing the scripts inside it should help out, aye?

# Build the go application into a binary
FROM golang:alpine as builder
RUN apk --update add ca-certificates
WORKDIR /app
COPY . ./
RUN CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -installsuffix cgo -o gatus .

# Run Tests inside docker image if you don't have a configured go environment
#RUN apk update && apk add --virtual build-dependencies build-base gcc
#RUN go test ./... -mod vendor

# Run the binary on an empty container
FROM scratch
COPY --from=builder /app/gatus .
COPY --from=builder /app/config.yaml ./config/config.yaml
COPY --from=builder /app/web/static ./web/static
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
ENV PORT=8080
EXPOSE ${PORT}

There are multiple things wrong in me this.

First, please stop putting your binaries in /app, please, pretty-please? We have /usr/local/bin/ for that.

Second, I thought that running go build without GOOS=linux would solve all of my problems. I was wrong, very wrong.

root@mon:~/gatus/gatus-2.8.1 # env CGO_ENABLED=0 go build -mod vendor -a -installsuffix cgo -o gatus .
package github.com/TwinProduction/gatus
        imports github.com/TwinProduction/gatus/config
        imports github.com/TwinProduction/gatus/storage
        imports github.com/TwinProduction/gatus/storage/store
        imports github.com/TwinProduction/gatus/storage/store/sqlite
        imports modernc.org/sqlite
        imports modernc.org/libc
        imports modernc.org/libc/errno: build constraints exclude all Go files in /root/gatus/gatus-2.8.1/vendor/modernc.org/libc/errno

Okay, check this out, the package is called modernc.org/sqlite and it says:

Package sqlite is a CGo-free port of SQLite.

SQLite is an in-process implementation of a self-contained, serverless, zero-configuration, transactional SQL database engine.

Of course it is. Looks like I have to port all of this to FreeBSD. Which, don’t get me wrong, I’m okay with doing that, but I thought that we have POSIX for a reason. notsomuch.

Okay, I’m an open-source guy, I’ll spend some time this weekend to port this to FreeBSD. Let’s look for another solution!

Here’s another one, it’s called statping, also written in Go, the readme is so promising.

No Requirements

Statping is built in Go Language so all you need is the precompile binary based on your operating system. You won’t need to install anything extra once you have the Statping binary installed. You can even run Statping on a Raspberry Pi.

Sounds good! Let’s try it out.

Again, I fetch the tarball, I extract and I bake make.

apt executed in Make

Of course it requires apt! Because not only we all run Linux, be we all run a specific distribution of Linux with a specific package manager.

While tweeting with anger, Daniel pointed out that I should tell them kindly and it’ll work out. I’m sure it will. Let’s hope I can make it work first. I don’t like just opening issues. I’d rather send a patch directly.

</rant>

Overall, now I understand why most *BSD folks use, what’s the word here? ah, yes, old-school software on their systems, like Nagios and the rest.

The developers of the New World Order will assume, always, you are running Linux, as Ubuntu, and you always have Docker.

Hopefully this weekend I will be able to port these software to FreeBSD, otherwise I will just use the Linux layer.

Like Rubenerd said, I am thankful that the mainstream-ness of Linux helped other Unix systems as well, but monocultures are destroying what people have spent years to improve.

Hopefully, next week, I will write a blog post on how to fix these issues and how I got all of those up and running.

That’s all folks…

Comments are back

When I started blogging 8 years ago I used WordPress. One of its features was comments. However, when I started my English blog (the one that you are reading right now) I chose Hugo and then migrated my Armenian blog to Hugo as well.

This had two amazing features. First, no more managing PHP and MySQL, since Hugo is a static sigh site generator, second, no more dealing with comments.

During the last years more and more people have been contacting me over email/Twitter/Telegram to give me feedback about a post that they read. This is mostly about my Armenian blog. I don’t get much feedback from the English blog, unless someone posts it on HackerNews (then I get A TON).

I started missing comments, a centralized place to read all the feedback and an easy way for the reader to post them.

In Hugo’s documentation I see there’s a section about comments but it recommends Disqus. I don’t like 3rd party services. Lucky someone on Twitter recommended an alternative, Isso!

Isso was very easy to deploy. I created a FreeBSD Jail, did a pip install isso and then setup a reverse proxy. Add some JS scripts here and there in the template, and it’s all done!

I’m not sure if I’ll be able to fight spam. I still need to setup an SMTP server so it emails the commenters if someone replied to their comments, but that’s a project for the weekend.

That’s all folks…

Music.app is a good radio app

As I mention in my other post, macOS also has Music.app, which as I said I will to try it out as well.

Turns out it’s really good! I’ve been listening to DeepHouseRadio all day. When the connection drops while I go to the kitchen to make some coffee, it buffers it properly. Although once it skipped and started playing the “next song” which was some media file.

While doing my testing, I realized that the Music.app has Radio included in it! It fetches the list of radio stations from TuneIn, which I loved using their app on my BlackBerry 9780 back in the day.

Good job Apple, not updating your QuickTime Player, but at least making sure that one of your out-of-the-box apps handles a thing properly.

That’s all folks…

Good bloggers write a lot

I’ve been thinking lately that I am NOT able to blog a lot and I always blame external factors, “Oh I don’t have time” or “oh there’s no pagination in my theme so there’s no point of blogging daily, yet.”

But in reality, turns out I’m just being lazy.

I’ve been reading Jamie Zawinski’s blog for years, via RSS, of course. Couple of days ago I opened it via my web browser, an woah those number hit me hard!

As you can see, there are 366 days in a year but jwz happens to have more posts per year than that! Look at year 2012, there are 870 posts!

I mean, I know that my favorite blogger, Rubenerd blogs a lot, but I never knew how much.

I know he has 10 posts per, and his blog currently says

Page 1 of 758 → Older posts

And I know he started blogging since 2004, so if you do the math using bc,

$ echo '(758 * 10) / (2021 - 2004)' | bc -l
445.88235294117647058823

Actually, lately I’ve learned about expr, it’s very handy in command line scripts!

$ expr \( 758 \* 10 \) / \( 2021 - 2004 \)
445

What I’m trying to say is, I don’t know how people blog regularly, it’s not that I don’t have any ideas in my head, there’s always something to say, something to share, something to write about. If it’s not technical then at least it’s political.

Recently Lilith suggested that I should try to allocate 30 minutes a day to write some posts, even if it would end up into the drafts. This is me trying to do that, while drunk 🙂

That’s all folks!

Two Colons Equals Modules

Days ago I tweeted a shell function which is part of jailio’s code base. Jailio is a project I’ve been working on for the last 6 months. As the name implies, it’s a container management software for FreeBSD Jails.

It has two unique things compared to other Jail management software. First of all, it has no dependencies, it’s written purely in Shell. You can say the same about BastilleBSD, however, Jailio’s second unique thing is that it uses base tools only and requires the base system only. For example, you need to have bastille_enable in BastilleBSD, it also uses its own config files, etc. In Jailio, you need to have jail_enable, because technically Jailio automates jail.conf files. It also uses my patch to automate the jail.confs in /etc/jail.conf.d.

Anyway, back to our topic about Colons and Modules.

I like modules, I got introduced to them when I started programming in school. In Syria, we learn programming at 7th grade but in our school we started a year early, so 6th grade. We always start with block diagrams and then Turbo Pascal!

Yes, 16-bit Turbo Pascal was my first programming language and it had the concept of modules which we called Units.

And then you have languages like C or Shell which don’t have modules. If you use modules you KNOW that it’s hard not to use modules after that.

While reading the source code of vm-bhyve I learned that you can use two colons (::) as part of the function name, which can give you an amazing new superpower to take over the world write cleaner code.

For me this was a life-changer. I write a LOT of Shell code. I ship them to production too. No, you don’t need to write everything in a fancy new language and run it on kubernetes, you can always use simple languages like Shell and run them in a FreeBSD Jail. Or in my case, write in Shell to automate FreeBSD Jails.

Here’s an example code with “modules” in Shell. Note, this works in FreeBSD’s shell, I have not tested other Shells yet.

main.sh

#!/bin/sh

. ./mod1.sh

mod1::func1

mod1.sh

#!/bin/sh

mod1::func1(){
  printf "Here I am, rock you like a hurricane\n"
}
antranigv@pingvinashen:~ % ./main.sh 
Here I am, Rock you like a hurricane

As you can see it all relies on the concept that the function name itself has two colons in its name.

Here’s the code from jailio that I tweeted.

jail::get_next_id(){
  expr $(
    ( grep -s '$id' /etc/jail.conf.d/* || echo '$id = "0";' ) |
    awk -F '[="]' '{print $3}' |
    sort -h |
    tail -1
  ) + 1
}

After tweeting the code above Annatar replied that this should NOT work elsewhere and that’s how I got introduced to The Heirloom Project which provides traditional implementations of the original Unix tools from the original Unix source code.

Hopefully, I will see more people using “modules” in Shell scripts. Hopefully this trick works in other Shell implementations like Bash and zsh.

That’s all folks.

The OS App vs The Browser OS

I like listening to online radios like anonradio and DeepHouseRadio, instead of me trying to organize my local library or listening the same music over and over again on Deezer, I get lazy and just use their HTTP link.

Like a sane person, I would use a media player to “open” these HTTP radio links. On my FreeBSD machine, all I need to do is mplayer http://the.domain/path/to/content, but on macOS it would not be that simple.

The default media player on macOS is QuickTime. Here is where my problems start. I open QuickTime Player, I set the location to the HTTP link and it all works fine. Until it doesn’t. A small network lag and it stops playing completely.

I am usually connected to the internet via a cable in my office or the house, but when I go wireless, there’s a blind spot in one of the rooms. My FreeBSD laptop with mplayer handles it all fine, but QuickTime? Not so much.

So I decided to use the “other” “Operating System” in macOS, also known as a browser, in this case Firefox. I open the link and it all works fine. Even if there’s a network lag, Firefox would handle it fine.

It’s sad funny how browsers are handling things better than native desktop programs these days.

While writing this blog-post I realized that macOS has another media player known as Music.app, so will try with that as well, let’s see how it will handle it.

That’s all folks.

Barcamp EVN21, or why we don't build more products

The year was 2021, the month, July, the day was the 10th and I was very happy. It was Barcamp Yerevan again, the new year of the tech industry, the day we all share knowledge, the day people come NOT to listen to talks but to take stickers and t-shirts instead, because it’s free, as in beer as well as in speech.

Not all people are like that, some of them give talks. I’ve been giving talks since Barcamp Yerevan 2016. Since it’s a free unConference, we get a lot of sponsors, from small outsourcing companies to large ISPs and Gambling-as-a-Service providers.

Usually, during an unConference such as this, there are 1) sponsored talks, by the sponsors, 2) selected talks, by individuals, which are selected by a committee and 3) unConference talks, where people just write on a wall “Talk about X at room Y, ZZ PM” and whoever is interested goes there to listen.

Usually, there’s this habit, that if the unconference talk is not good, then people leave the room by smashing the door on the way out. Usually, the selected talks are good, because good job committee, usually the sponsored talks are good, because sponsors don’t want to send an engineer who’d give a bad talk.

But this year was not a usual one. This year was the exact opposite.

The uncoference talks were awesome, people from random companies were talking about how to work remotely, how to work from outside the heart and the capital of Armenia, Yerevan. People were talking about how to start a community. People were talking about audio system and audio engineering.

The selected/sponsored talks were the… I’m not sure I know how to describe this, but, they were what they are supposed to be, sponsored talks by sponsors.

Here is an example. A system engineer fellow talks about infrastructure automation, how tools like Terraform are cool, what is an automat… no sorry, he did NOT talk about the benefits of an automated infrastructure nor what problems it solves. I wondered why.

At the end of the talk someone asked “so have you implemented this at YOUR company?” and the fellow answered “Well, not really, some bits here and there”, and I got the answer to my why question.

He did not know, because he was not talking from experience. That’s why there was no storytelling, there was no “sharing” of experience. It was only a talk, which is what the sponsored company was aiming for anyway.

Now for me, a systems engineer, I can see BS lack of experience like that in a minute, but I asked my friends if ALL the talks were the same, the marketing ones, the media ones, the ones about “how to grow your company,” and guess what, all of my expert friends in other fields agreed with me.

We also had panels. I was on one of those panels, I think it was called “Security Panel” which was supposed to be about… Security, as in InfoSec. But instead we talked about the war and the post-war status of the “cyber” security field in the country.

Last but not least, the guests, they were awesome, all of them, they shared a LOT of knowledge with the audience, which I hope will have an impact long-term.

Alas, that’s the pain of running a free, corporate-sponsored (un)conferences. You give voice to people who have the money, which not necessarily have the knowledge nor the experience. And this is why we don’t have more product companies in Armenia. We are not producers, we don’t have the experience. We are consumers, we are not part of open-source communities, and if a fellow is then everyone will point out as if it’s some god-ish action to contribute to software.

Hopefully, next year will be better.

P.S. Every year I give the last talk on the last day, since people stick around and ask me questions and I don’t like to ignore questions or free the room for the next speaker. All my previous talks are on my personal page on the new Barcamp Yerevan website. This year I was at 10:30AM… Most of the organizers who knew me personally were afraid that I’d oversleep. Luckily, such disaster was averted thanks to Syuneci.

That’s all folks.

How I got fired from my first tech job

My daily routine is usually the same, wake up, go to work, do a lot of meetings, chat, email, code, sleep and repeat. Which means that I don’t have new things to talk about. However, since I decided to blog regularly, here’s a blast story from the past 🙂

I grew up in Syria and it’s a cultural thing that we work from a very early age. I got my first job when I was 11 years old. During the summer I worked as a stonesetter, my salary was 200 Syrian Liras per week, back in the day that would be 4 US Dollars.

I loved that craft, looking deeply into the pins and understanding where the gems and diamonds would go, how to close the pins properly so it would sit there for years.

However, I also had a love for computers, I got interested when I was introduced to Unix, I wanted to use Aircrack-ng to hack the neighbor’s WiFi Access-Point so I get free internet access. Inet access was not only expensive, but you had to wait 6 to 12 months to get one. I got Slitaz Linux up and running, it included Aircrack-ng in it and cracked the network, I still remember the password, it was 11111222223 with WEP algorithm. Hrach, if you are reading this, I’m sorry that I never told you about it, but thanks to you I got into computers 🙂

When I was 14 I had to deliver gold to a partner workshop, on the way, right at the beginning of Sulaymaniyah Street I noticed a large computer shop. Very beautiful, a lot of computers, laptops, hell, there was a gaming PC with 3 screens (That was the first time I saw a desktop with 3 screens!). After I delivered the gold, on my way back, I entered the shop, I got introduced to the owner. Turns out they were an official representative of companies like Dell, HP, Asus, etc.

I talked with the owner about some of my projects, that I was installing Linux machines in school and that I was trying to make a map with all access points in Aleppo with their passwords.

After 20-30 minutes of chit-chat, he offered me a job. I was supposed to 1) Format computers (as we used to say), that is installing a fresh OS and setting up software 2) Help the other employee to deploy networks at schools 3) Help customers buy new computers when they arrive.

I worked there for 3 months, I was getting paid 250 Syrian Liras per week, that is 5 USD back in the day, plus some bonuses every time I would sell a device or fix networking issues at the schools.

One day customers arrived (a man with his wife), they were having problems with a laptop that they owned, I fixed the issue on the spot and asked nothing in return. They asked if I could come and fix a similar issue on their desktop at home, I told them I would but I cannot right now as the owner is not here. I wanted to give them a business card to call us later but we were out of those, so I gave them my cellphone number.

An hour or so later the owner came back, I told him about what happened and went back to my room to fix an HP laptop that had a melted keyboard and I started blaming AMD for that 🙂

The couple called, I told my boss, he told me “Okay, go to their place and fix it, don’t charge them anything”. So that’s what I did.

I came back to the office an hour later, the owner was sitting in front of his desk and told me to sit in front of him. Then he said, “Are you trying to steal my clients?”.

I got confused, I had no idea what is he talking about, “Sorry, what do you mean? I didn’t understand what are you implying”. He answered, “You gave them your cellphone number, so they start calling you and pay you instead of us. You’re fired”.

I didn’t know what to respond, I didn’t have those intentions, I was just doing my job.

I took my backpack and I left. I was crying the entire time, walking back home, listening to Star Wars Galactic Battlegrounds’ OST.

To make things worse, when I arrived at home my mother told me “Why are you so much into computers? It’s not that it even pays well, you know you have to study and graduate Pre-Secondary Education this year”, little did she know, that as of right now, I will not be paid at all while “doing computers”.

Years have passed and I moved to Armenia during the Syrian war. While working as a waiter for a year, I found an “Armenian Linux” and the company responsible for it, Turns out they were a huge software development company. I wrote a patch for the “splash screen”, I gave them the patch, on a USB drive.

The CEO of the company said “What are you doing next Monday?”, “I have to go to university” I replied, as I was an undergrad learning English and Communications. “Well, after the university you’re coming here, you’re hired”.

Oops, flashbacks, what am I supposed to do now?

I looked left and right, there were all these desktops running Linux, the engineers on the top floor were working on robotics, so I said “Deal!”.

I learned that day, that no matter how bad of an experience you get, the next time will probably be different. Unless it’s Windows, that thing always fails.

That’s all folks.

VNET Jail HowTo Part 2: Networking

As always, Dan has been tweeting about VNET Jail issues, which means it’s time for another VNET Jail post.

This post assumes that you’ve read the original post on VNET Jail HowTo.

In Part two we will discuss Networking.

We will use PF as a firewall to do things like NAT.

If you need more help please check the FreeBSD Handbook: Chapter – Firewalls or send me an email/tweet.

At this point (from the last post) we were able to ping from the Jail to the Host.

root@www:/ # ping -c 1 10.0.0.1
PING 10.0.0.1 (10.0.0.1): 56 data bytes
64 bytes from 10.0.0.1: icmp_seq=0 ttl=64 time=0.087 ms

--- 10.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.087/0.087/0.087/0.000 ms

Now we will setup PF on the host by adding the following to /etc/pf.conf

ext_if="em0"
jailnet="10.0.0.0/24"

nat pass on $ext_if inet from $jailnet to any -> ($ext_if)

set   skip on { lo0, bridge0 }
pass  inet proto icmp
pass  out all keep state

We also need to enable IP Forwarding in the kernel

Add the following in /etc/sysctl.conf

net.inet.ip.forwarding=1

And now execute

sysctl -f /etc/sysctl.conf
service pf restart

That should be it, now your Jail should be able to ping the outside world

root@zvartnots:~ # jexec -l www
You have mail.
root@www:~ # ping -c 1 9.9.9.9
PING 9.9.9.9 (9.9.9.9): 56 data bytes
64 bytes from 9.9.9.9: icmp_seq=0 ttl=61 time=2.566 ms

--- 9.9.9.9 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 2.566/2.566/2.566/0.000 ms
root@www:~ # 

If you setup a resolver, you should also be able to ping domain names as well.

root@www:~ # echo 'nameserver 9.9.9.9' > /etc/resolv.conf 
root@www:~ # ping -c 1 freebsd.org
PING freebsd.org (96.47.72.84): 56 data bytes
64 bytes from 96.47.72.84: icmp_seq=0 ttl=53 time=133.851 ms

--- freebsd.org ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 133.851/133.851/133.851/0.000 ms

Now, for a more complicated setup that assumes no firewalls and multiple IP addresses, where each Jail has its own IP address. I have a similar setup at home where my ZNC server Jail has its own IP address by connecting the physical NIC to the same bridge as the ZNC Jail.

In my rc.conf on the host

ifconfig_em0="inet 192.168.0.34 netmask 255.255.255.0"
defaultrouter="192.168.0.1"

cloned_interfaces="bridge0"
ifconfig_bridge0="addm em0"

Here’s an example with jail.conf

znc {
	$id		= "52";
	$addr		= "192.168.0.252";
	$mask		= "255.255.255.0";
	$gw		= "192.168.0.1";
	vnet;
	vnet.interface	= "epair${id}b";

	exec.prestart	= "ifconfig epair${id} create up";
	exec.prestart	+= "ifconfig epair${id}a up descr vnet-${name}";
	exec.prestart	+= "ifconfig bridge0 addm epair${id}a up";

	exec.start	= "/sbin/ifconfig lo0 127.0.0.1 up";
	exec.start	+= "/sbin/ifconfig epair${id}b ${addr} netmask ${mask} up";
	exec.start	+= "/sbin/route add default ${gw}";
	exec.start	+= "/bin/sh /etc/rc";

	exec.poststop   = "ifconfig bridge0 deletem epair${id}a";
	exec.poststop  += "ifconfig epair${id}a destroy";

	host.hostname = "${name}.bsd.am";
	path = "/usr/local/jails/${name}";
 	exec.consolelog = "/var/log/jail-${name}.log";
	persist;
}

And that’s pretty much it!

That’s all folks.