HN user

_paulc

197 karma
Posts0
Comments72
View on HN
No posts found.

As a long term FreeBSD user (since 2.0) and advocate, my view is that FreeBSD should focus on its niche as a rock-solid server operating system. For most developers buying a MacBook and SSH-ing into a server is probably the right answer (or running a VM if you really need something local). The level of effort to match the MacBook user experience feels like a lost cause (Linux has been trying to do this for decades with significantly more resources) and it would feel more useful to use this funding to focus on the server side.

That's really useful (I was trying to work out how to do this without using a custom image) but I would just note that there actually is a FreeBSD 13.1 image available under Images -> Partner Images -> FreeBSD (from the FreeBSD Foundation).

Oracle Cloud have a very generous free-tier for the arm64 boxes and I'm running 2 x arm64 instances (2 CPU / 12GB RAM each) - been really reliable so far though I'm not doing that much on them.

A toy DNS resolver 4 years ago

Simple python version which does a bit more validation (checks response matches query) and also supports CNAMEs and different record types (37 lines - using dnslib library) - though there is still a lot of logic missing (handling failed NSs, IPv6 only NSs, cycles etc)

    from dnslib import DNSRecord,DNSError,QTYPE
    
    ROOT_NS='198.41.0.4'
    
    def find_cname(a,qtype,cname):
        for r in a.rr:
            if QTYPE[r.rtype] == qtype and r.rname == cname:
                return str(r.rdata)
            elif QTYPE[r.rtype] == 'CNAME' and r.rname == cname:
                return find_cname(a,qtype,str(r.rdata))
        return resolve(str(r.rdata),qtype,ROOT_NS)
    
    def resolve(name,qtype='A',ns=ROOT_NS):
        print(f"dig -r @{ns} {name} {qtype}")
        q = DNSRecord.question(name,qtype)
        a = DNSRecord.parse(q.send(ns))
        if q.header.id != a.header.id:
            raise DNSError('Response transaction id does not match query transaction id')
        for r in a.rr:
            if QTYPE[r.rtype] == qtype and r.rname == name:
                return str(r.rdata)
            elif QTYPE[r.rtype] == 'CNAME' and r.rname == name:
                return find_cname(a,qtype,str(r.rdata))
        for r in a.ar:
            if QTYPE[r.rtype] == 'A':
                return resolve(name,qtype,str(r.rdata))
        for r in a.auth:
            if QTYPE[r.rtype] == 'NS':
                return resolve(name,qtype,resolve(str(r.rdata),'A',ROOT_NS))
        raise ValueError("Cant resolve domain")
    
    if __name__ == '__main__':
        import sys
        def get_arg(i,d):
            try: return sys.argv[i]
            except IndexError: return d
        print(resolve(get_arg(1,"google.com"), get_arg(2,"A"), get_arg(3,ROOT_NS)))
Disclaimer: I am author of dnslib [https://github.com/paulc/dnslib]

Edit: Better CNAME support

dnslib author here - wasn’t expecting to see this so thanks for the reference.

Key thing I learnt writing dnslib (which was originally to provide a DNS API for an application) is that DNS is actually a very dynamic protocol but the complexity of mainstream servers like BIND makes it hard to do a lot of the things that you can actually do. There are a lot of problems (in particular in the service discovery space) which can be solved much more easily using DNS rather than inventing something separate.

As an aside if you want an authoritative DNS server I would look at KnotDNS [1] - you can avoid all the zone file cruft and interact with it using a sensible API. If you want to write a dynamic DNS app I would look at @miekg’s excellent Go library [2]

[1] https://www.knot-dns.cz/

[2] https://github.com/miekg/dns

The more surprising point was the disparity in staffing levels which multiplies the cost differences:

“For example, in New York, the number of workers at the face of the tunnel can be up to four times the number of workers required in Germany or Austria for similar projects.”

I've been a FreeBSD user since 2.05 (1995) and a strong supporter - FreeBSD still excels as an ultra-stable 'old-school' UNIX server OS (which to be honest meets a lot of use-cases more simply than a lot of modern alternatives). That being said this sort of post isn't helpful as advocacy - as others have notes it is pretty shallow and to be honest most people are probably better off running Linux if this is what they are used to.

To be honest it’s probably not worth running FreeBSD on a laptop/desktop - it’s really a server operating system. If you are looking for a well engineered, stable, ‘traditional’ UNIX system sitting in a rack and happy with a terminal interface it’s an amazing OS. Lots of people however seem to be trying out on laptops/desktops and being disappointed which isn't a huge surprise.

(FreeBSD user since 2.0.5 - 1995)

Hello World 7 years ago

As it's not on Drew's list:

Nim:

  $ cat hello.nim
  stdout.write("hello, world!\n")
Static (musl):
  $ nim --gcc.exe:musl-gcc --gcc.linkerexe:musl-gcc --passL:-static c -d:release hello.nim
  $ ldd ./hello
  not a dynamic executable

  Execution Time: 0m0.002s (real)
  Total Syscalls: 16
  Unique Syscalls: 8
  Size (KiB): 95K (78K stripped)
Dynamic (glibc):
  $ nim c -d:release hello.nim
  $ ldd ./hello
  linux-vdso.so.1 =>  (0x00007ffc994b6000)
  libdl.so.2 => /lib64/libdl.so.2 (0x00007f7c88785000)
  libc.so.6 => /lib64/libc.so.6 (0x00007f7c883b8000)
  /lib64/ld-linux-x86-64.so.2 (0x00007f7c88989000)

  Execution Time: 0m0.002s (real)
  Total Syscalls: 42
  Unique Syscalls: 13
  Size (KiB): 91K (79K stripped)
Which I think is actually pretty reasonable for a high-level GC'd language.

This looks really good, I've used ccrypt (#1) for years as a simple Unix-y encryption tool to avoid the complexity of GPG (though this is symmetric encryption only so you need to have a secure way to exchange keys).

I just added a pull-request to allow the recipients flag to also be specified as a https:// or file:// URL - this is mostly useful to use the GitHub <user>.keys endpoint to grab user keys eg.

  ./age -a -r https://github.com/<user>.keys < secret
will encrypt using <user>'s GitHub SSH public keys.

#1 http://ccrypt.sourceforge.net

#2 https://github.com/FiloSottile/age/pull/43

Actually this is pretty simple if you use ConfigParser properly:

  # test.ini
  [host1]
  ip = 1.2.3.4
  [host2]
  ip = 5.6.7.8
  [host3]
  ip = 9.10.11.12

  # config.py
  import configparser

  c = configparser.ConfigParser()
  c.read("test.ini")
  ips = [ c[host]['ip'] for host in c.sections() ]

ed(1) is actually quite usable, I remember editing lots of documents using ed/troff at university in the early 80s as still occasionally drop into ed if I wasn't to do a small change to a simple txt file (I remember that using vi was frowned on as an egregious waste of memory)

This lines up with my experience. Strangely I had someone submit a bunch of slightly passive-aggressive "Py3 support" pull requests to a couple of my repos which were basically the result of running 2to3 on the code. They hadn't even bothered to run the unit tests (which obviously failed spectacularly). It did however prompt me to get Py3 support working properly which was actually a good thing.

There are lots of jail wrappers but in most cases it is just as easily to just take the time to understand how jail.conf works and use this (see FreeBSD jails the hard way [1]). It's fairly easy to just use zfs clones to create jails and customise the exec.prestart/exec.start functions to do automatic provisioning and configuration (eg. I store the port forwards in a variable for each jail and process this and automatically setup pf rules when the jail starts).

[1] https://clinta.github.io/freebsd-jails-the-hard-way/