Nominet EGM, March 2021

Members of the UK’s domain registry, Nominet, have called an EGM to get rid of most of the governing board. After fighting tooth and nail, chairman
Russell Haworth resigned yesterday (Sunday), but other controversial board members remain.

Unusually for me, this year’s report will be updated live. But you’ll have to refresh your browser manually!

Note that this is paraphrased!

The argument is over the direction of Nominet. When it was founded, the idea was for it to take over from the Naming Committee and run the UK’s top level DNS servers. The Naming Committee was overwhelmed, and it was felt reasonable that a new organisation could take over the work, funded by a small fee for new registrations.

This was inevitably going to lead to a surplus income, which was supposed to be distributed for the public benefit, keeping reasonable reserves in case of major court cases.

In 2006 Nominet altered it’s remit to allow other activities, which I warned about at the time. It turns out I was right (as usual), and in the intervening years the board diversified into such things as self-driving cars and subsidising a cyber-security business, in competition with some of the members who were paying for it. Network Solutions all over again.


Mark Wood opens, and acknowledges that the board hasn’t been listening to members. Grateful to Russell Howarth for driving growth.

Invited Simon Blackler to speak for a few minutes. Mark Wood says he declined.

Now going to member’s questions, starting with those sent in advance.

Question: Why has the board predicted chaos if the board changes?

James Bladel: It will, indeed, fall apart without the experience of the existing board. As the board has prevented the second motion to appoint a new board, it will delay reforms.

Question: The campaign by the board has been dirty. How will you heal the rift.

Rob Binns: “We will continue an open dialogue” and make sure there is a meaningful two-way dialogue.

Question: Ester. Why was second resolution (Appoint new directors) blocked?

James Bladel: Don’t ask me – ask Roy. But we have established processes, so we’re not going to make an exception just because the members vote to have one.

Question: What are the chances of the government stepping in and resulting in a price rise?

Steven Page: There is a possibility, but we don’t know for sure. “Nominet is at the heart of digital Britain”. Sounds to me like a FUD pitch.

He’s just suggested the NHS might collapse if the board is removed, as Nominet is critical infrastructure.

Question: Why were Registry Advisory Council idea underway before the EGM?

Ellie: We wanted to find another way to get feedback. She described it as a “registry business”.

Question: What are the board’s future plans depending on whether the resolution passes or not?

Rob Binns: “As a board we will lay out a process that will drive that engagement” regardless of the outcome.

If the motion passes (board half fired) we will have a focus on stability.

Questions: What justifies huge increases in board remuneration.

Please generate and paste your ad code here. If left empty, the ad location will be highlighted on your blog pages with a reminder to enter your code. Mid-Post

Mark Wood: Our strategy was to diversify into alternative revenue streams as a hedge against possible income decline. Stated that costs would increase (but didn’t explain why).

Jane Tozer: We take the pay issue seriously, so we’ve frozen it. Our executive team has outperformed on its targets. Appears to be reading a written statement. It benchmarks pay against similar sized technology companies. (Odd, as these are profit driven – Nominet is supposed to be running a DNS).

Question: What is the cross-subsidy between domains and cybersecurity?

Ellie: We’re not cross-subsidising.

Question: One of the problem is lack of engagement. Would the board introduce members meetings?

Anne Taylor: As a board want to export all ways of engaging. It was a bad move to shut down the forum.

David Thornton: Shutting down the forum was inflammatory but needed a re-vamp.

Question about discounts for .co.uk and .uk together. Irrelevent.

Question: Why has it taken so long to realise members are not happy?

Mark Wood: We’ve missed some signals. Simon Blackler has run a good campaign and raised a lot of issues. We want to make these changes and accelerate them.

Question: Will be bring back member engagement lunches.

Ellie: Yes, stuff like that. “We’re going to need to find more ways to get the views of the network”.

Question: Why can’t we hear from Simon Blackler?

Mark Wood: It’s not a debate; it’s a company EGM. Simon Blackler declined to speak.

Question: Has the current board makeup been complicit in side-lining members’ decent?

James Bladel: I don’t think this has really happened as we have vigorous debates on the board.

Question: What’s Russell’s status right now?

Mark Wood: Russell actually stood down from the board on Sunday. (Subsequently confirmed that the registration was accepted).

Question: About CNI status.

Stephen Page: We’re not, but we’re looking at what would happen if were were designated as such. It could push up our costs. It depends which part of the regulatory system takes us on. We hope it won’t increase prices.

Question: If the broad is critical, what is the plan if anything happened to it?

Rob Binns: Yes, we have a contingency plan. The motion is to remove various members of the board. We’d have to think about how we’d manage that. In any scenario we’ll continue with improved engagement. Didn’t explain what the plan was.

Question: Similar to previous on member engagement.

Mark Wood: Repetitive waffle. Sounds like they’re talking out more difficult advance questions.
James: Bladel: More repetitive waffle. Absolutely nothing that hasn’t been said before. “We need to focus on the future.” “Rebuild relationship”.

Mark Wood: Largest turnout in Nominet’s history. As the whole board has said, Nominet will change as a result of this. I believe it will be easier if we don’t change the board. Closing the member forum was a mistake. We’ll find new and better ways.

We also need to bring the government into management of Nominet as a stakeholder. Nominet delivers brilliant service, does an important job, and does very well.

Don’t Do This To Fix Slow WiFi

Have you seen adverts like this popping up on dodgy web sites? If you’ve ever clicked on one, you go to a page where someone explains that ISPs are deliberately slowing down people’s internet connections, but for £50 they’ll sell you a miracle box that will thwart your ISP’s attempt do to this.

It is, of course, complete garbage. What they’re actually selling is a generic Chinese WiFi repeater, which they’re calling a WiFi Blast. Whether this will help with anything is debatable; but it might.

What a WiFi repeater does is act as an intermediate station between two others – i.e. your current wireless AP and the thing you’re trying to connect. If the distance is too far for the signal to propagate, the relay sits in the middle where it can see both ends, and passes the messages back and forth.

Unlike normal radio repeaters, a WiFi repeater is going to be half duplex, as it’s not going to be able to transmit and listen at the same time – the input would be swamped. This is obviously going to be slower than a direct connection, but it’s useful to cover long distances.

Whether it’s useful to get through walls is highly debatable. RF propagation is a funny thing. Run a wire instead.

The sales pitch likely breaches dozens of different advertising laws. But if you’re determined to buy one anyway, they’re about £10 on Amazon. Repeaters do have their uses, including linking a wired ethernet device to WiFi, but changing the speed of your Broadband by some miracle isn’t one of them. And no, I don’t get a kick-back if you buy one through this link.

USB Ethernet on FreeBSD

Why would you even want to cripple your network connection by using USB instead of a proper NIC? Well if you have no free PCIe slots you might have to, as is the case if you’re using a very small computer as a router/gateway.

But why would you use a small computer as a FreeBSD router? Well FreeBSD doesn’t keep crashing like the purpose-built routers we all know and hate. Yes, that’s right – you can use FreeBSD in your router and it won’t crash. Having to turn your network router on/off periodically is, it turns out, entirely optional.

So back to these small computers: the problem is they tend to have but one Ethernet port, and no slots to add a second. They do tend use USB as the only way of expanding the hardware. But assuming you don’t have a crazy fast WAN you can still get away with a USB network adapter on that. Perhaps don’t bother using a bunch of them to make a switch though, but for a single second port and not much else going on, it works just fine.

But here’s the thing – FreeBSD doesn’t support USB3 Ethernet chips very well. In fact the only one I know of is the ASIX88179, and there are mixed reports about how well this works these. I’ve ordered one to take a look at.

In the mean time, the smart money is on USB2; and although you can get 1Gb USB2->Ethernet chips, a quick calculation will show you can’t do a sustained 1Gb transfer through it. But if your WAN is <100Gbs, this won’t actually matter.

There are, fortunately, plenty of USB2->100baseT chips to choose from, and these are the safest options. I’ve extracted this list from the documentation:

ADMtek AN986 Pegasus
ASIX AX88172,AX88178,AX88772,AX88772A,AX88772B and AX88760
CATC EL1210A (10Mb only!)
Kawasaki LSI KL5KLUSB101B
RealTek RTL8150
SMSC LAN95xxx
Davicom DM9601

I’ll be doing some experiments with a few of these to see which work best, but if you’ve got any further information please comment!

Incidentally, thus far I’ve been happy with ASIX chips. That said, I’ve not tested them, or the others, to their limits yet. They do seem stable though.

Networking FreeBSD Jails

Or port forwarding to a jail

I’ve already explained how easy FreeBSD jails are to set up and use without resorting to installing heavy management tools, but today I thought I’d add a bit about networking. Specifically, how do you pass traffic arriving on a particular port to a service running inside a jail?

It’s actually very easy. All you need is a very local network inside FreeBSD, natted to the one outside.

Suppose you have your jail.conf set up as per my previous article. Here’s an excerpt:

tom { ip4.addr = 192.168.0.2 ; }
dick { ip4.addr = 192.168.0.3 ; }
harry { ip4.addr = 192.168.0.4 ; }

The defaults were set earlier in the file; the only thing that’s unique about each jail is the IP4 address and the name. What I didn’t say at the time was that 192.168.0.0 could have been on an internal network.

To define your local network just define it in rc.conf:

cloned_interfaces="lo1"
ipv4_addrs_lo1="192.168.0.1-14/28"

This creates another local loopback interface and assigns a range of IPv4 addresses to it. This can be as large as you wish, but I’ve defined 1..14 (with appropriate subnet mask) because they’ll be listed every time you run ifconfig!

Next you’re going to need something to do the natting. pf is your friend here. I struggled for years using ipfw before I discovered pf.

Enable pf in rc.conf too:

pf_enable="yes"

And you’ll need an /etc/pf.conf file to do the magic. I like pf – it’s easier for my brain to understand than most. Here’s an example file:

PUB_IP="192.168.1.217"
INT="bge0"
JAIL_NET="192.168.0.0/24"
TOM="192.168.0.2"
DICK="192.168.0.3"
HARRY="192.168.0.4"
scrub in all
nat pass on $INT from $JAIL_NET to any -> $PUB_IP
block on $INT proto tcp from any to $PUBIP port 111
rdr pass on $INT proto tcp from any to $PUBIP port 3306 -> $TOM
rdr pass on $INT proto tcp from any to $PUBIP port {21,80,443} -> $DICK
rdr pass on $INT proto tcp from any to $PUBIP port 81 -> $HARRY port 80

So what’s going on?

I’ve used a few macros. PUB_IP is your public IP address, and INT is the interface it’s on. pf may figure some of this out, but I’m being explicit.

TOM, DICK and HARRY are the IPv4 addresses of the jails.

Next I’m scrubbing all interfaces (normally a good idea, but you don’t have to). But the next line is important – it uses nat to allow stuff on your jail network to talk to the outside world.

The following line is where you might want to block more stuff – in this case NFS on port 111. Then we’re back to jail things for the final three lines. They’re pretty self-explanatory, but here’s an explanation anyway.

Let’s say the tom jail is running a MariaDB server on port 3306. The first line takes anything arriving on port 3306 and sends it to tom’s jail IP. Simple. It can reply because of the nat line earlier.

dick is running a web and ftp server, so ports 21,80 and 443 are sent there. The pf syntax lets you do nice stuff like this with the {..}

Finally we come to harry. Here we’re running an http server on port 80, but to make it accessible externally we’re mapping it to port 81 as otherwise it would clash with dick. In other words, if you don’t specify a destination port in the redirect it will assume the same as the source port.

And that’s it! When you jail is started you will see an interface lo1 with the IP address defined in /etc/jail.conf and assuming you have something sensible in /etc/resolv.conf you’ll have a jail that looks like it’s running behind a NAT router with port forwarding.

Of course, if you don’t need to map a jailed service to an external IP address, don’t! Jails can access services on each other using their own virtual network.

What’s a “digital motor”?

It’s certainly not just a fancy name for an electric motor, but the term “digital” was added by Dyson (I believe) to make his vacuum cleaners sound more exciting. Before that they were known as “brush-less” DC motors.

In simplistic terms, an electric motor works by having a moving electromagnet attracted to a fixed magnet, with the electromagnet on the spinning bit in the middle. Turn on the current and the electromagnet gets pulled towards the fixed magnet. Yeah! We have motion. However, when the two magnets reach each other they’re going to “stick”, so at that point you need to reverse the polarity of the current in the electromagnet so it changes from North to South, and it will then push itself away from the fixed magnet – carry on spinning.

In a traditional motor this is achieved using a commutator, which contains two contacts (+ve and -ve) called “brushes” which wipe against contacts on the spinning bit and provide power to the electromagnet. As the motor turns 180 degrees, the contacts are arranged so that the polarity is reversed – pull becomes push and vice versa, and the motor continues to rotate another 180 degrees – where it repeats.

To run smoothly you need more than two magnets, so something is always pulling, but that’s the general idea.

These brushes are a PITA. They cause friction, wear away, and make sparks. But it’s 19th Century technology and the best we had for a long time.

A brushless DC motor uses electronics to switch the polarity in the electromagnet. It uses a sensor on the spinning bit to work out which electromagnets need current and when. This can be done with analogue or digital electronics according to taste. Hence someone decided to call it “digital” after a while, because digital was “cool”. However, a digital motor has many advantages – not least of which is getting rid of the hated brushes and the need to replace them periodically. If you have smart electronics the motor can be more efficient by applying exactly the right current for requirements, and to more electromagnets that would be practical otherwise. It’s similar in a way to electronic fuel injection in vehicle engines (if you’re old enough to remember carburettors) – if designed well they can put in exactly the right power at the right time, saving energy and improving performance.

This applies to DC motors only. AC motors are a different matter, and may or may not contain a commutator . There are many types, and some do need a
commutator to activate the electromagnet in the rotor.
The characteristics and uses of these different motor types is beyond this post, but it’s worth noting that the Induction Motor (aka asynchronous motor), that was patented in 1888 by Nikola Tesla. This induces a current to flow in the rotor coils using coils in the casing, and therefore dispenses with the need for a contact. If you can use an induction motor instead of a brushed AC motor, do so. Industrial AC motors often use a commutator as they can generate more power for a given size, at the expense of more maintenance. It was also, at one time, easier to vary the speed of a brushed AC motor.

Update: Well, that’s what I get for trying to write a post on mobile phone using an Android App and “smart” keyboard and a screen so small I can barely see it – it swapped “commutator” for “communicator” in several places in the text (but not all). Thanks to the anonymous Virgin Media user who left a comment to this effect! There are probably plenty more typos of a similar nature if anyone wants to look. It also hyphenated brushless :-)

Wake on LAN with FreeBSD and Broadcom Ethernet

To be fair, the Broadcom Ethernet adapter chips aren’t the best supported by FreeBSD. They’re okay, but for FreeBSD Intel rules the roost at 1-Gig and Chelsio at 10-Gig plus.

Unfortunately you may have no choice, as Broadcom chips are built in to the motherboards on some HP servers; notably the Microservers.

The Microserver Gen 7 is a great little box. I love them. I’m not so keen on the Gen 8 or Gen 10, as they’ve dropped a lot of the features that make the Gen 7 so adaptable.
So after much investigation, I decided to either forego WoL support, or bung in a cheap Realtek card simply to wake them up, but with only two PCIe slots, it was a pity to waste one on a better supported Ethernet NIC. That was a long time ago, and I’ve had one eye out for a fix for a while.

And then last year someone looked at it, and I found references to this in bug tracker. Unfortunately I don’t know who to credit with the fix, and it hasn’t made it to the kernel yet as it’s not 100%, but if you need it I’ve patched the 12.1 driver based on all the notes I could find.

There’s a question about the new driver’s correct operation on laptops. Why you’d be using WoL on a laptop eludes me; but for the Microservers it just works.

Download the patched driver ‘C’ file above (as edited by yours truly – no guarantees), and copy it to /usr/src/sys/dev/bge/if_bge.c, rebuild the kernel and away you go. As it was a bug with the state the chip was left on shutdown, you have to reboot the NEW kernel to shut down in the correct state for WoL to work. Don’t forget to enable WoL in the Microserver BIOS too.

Although this fixes the WoL issue, I know the Broadcom chips are capable of more than the driver – for example jumbo packets. If you want better network performance with a Microserver, add a dual-port Intel Ethernet card instead. Sorry, HP/Broadcom.

FreeBSD in Godden Green

What is going on with FreeBSD in Godden Green in Kent, UK? Jobsite has been spamming me with junior/mid-level programmer roles mentioning FreeBSD for months now, and I’m getting curious!

I have an alert set up so whenever FreeBSD is mentioned I get a ping, as I like to know what’s going on. This isn’t one of the usual suspect AFAIK – they might even be interesting!

The Huawei thing

A few months ago I was asked for comment on the idea that an embattled Theresa May was about to approve Huawei for the UK’s 5G roll-out, and this was a major security risk. Politics, I assumed. No one who knew anything about the situation would worry, but politicians making mischief could use it to make a fuss.

Now it’s happened again; this time with Boris Johnson as Prime Minister. And the same old myths and half-truths have appeared. So is Chinese company Huawei risky? Yes! And so is everything else.

Huawei was founded by a brilliant entrepreneurial engineer, Ren Zhengfei in 1987, to make a better telephone exchange. It came from the back to become the market leader in 2012. It also made telephones, beating Apple by 2018. While the American tech companies of the 1980’s grew old and fat, Huawei kept up the momentum. Now, in 2020, it makes the best 5G mobile telephone equipment. If you want to build a 5G network, you go to Huawei.

Have the American tech companies taken this dynamic interloper lying down? No. But rather than reigniting their innovative zeal, they’re using marketing and politics. Fear, Uncertainty and Doubt.

Some arguments:

“Huawei is a branch of the evil Chinese State and we should have nothing to do with it.”

Huawei says it isn’t, and there’s no evidence to the contrary. The Chinese State supports Chinese companies, but that’s hardly novel. And whether the Chinese State is evil is a subjective judgement. I’m not a fan of communist regimes, but this is beside the point if you’re making an argument about technology.

“Huawei is Chinese, and we don’t like the government or what it does”.

So we should boycott American companies because we don’t like Trump? We do business with all sorts of regimes more odious that the CPC, so this is a non-argument. You could make a separate argument that we should cease trade with any country that isn’t a liberal democracy, but this could be difficult as we’re buying gas from Russia and oil from the Middle East.

“Huawei works for the Chinese secret service and will use the software in its equipment to spy on, or sabotage us.”

First off, Ren Zhengfei has made it very clear that he doesn’t. However, there have been suspicions. In order to allay them, Huawei got together with the UK authorities and set up the HCSEC in Banbury. Huawei actually gives HCSEC the source code to its products, so GCHQ can see for itself; look for backdoors and vulnerabilities. And they’ve found nothing untoward to date. Well, they’ve found some embarrassingly bad code but that’s hardly uncommon.

Giving us access to source code is almost unprecedented. No other major tech companies would hand over their intellectual property to anyone; we certainly have no idea what’s inside Cisco routers or Apple iPhones. But we do know what’s inside Huawei kit.

“Because Huawei manufactures its stuff in China, the Chinese government could insert spying stuff in it.”

Seriously? Cisco, Apple, Dell, Lenovo and almost everyone else manufacturers its kit in China. If the Chinese government could/would knobble anything it’s not just Huawei. This is a really silly argument.

Conclusion

So should we believe what the American’s say about Huawei? The NSA says a lot, but has offered no evidence whatsoever. The US doesn’t use Huawei anyway, so has no experience of it. In the UK, we do – extensively – and we have our spooks tearing the stuff apart looking for anything dodgy. If we believe our intelligence services, we should believe them when they say
Huawei is clean.

Being cynical, one might consider the possibility, however remote, that America is scared its technology companies are being bested by one Chinese competitor and will say and do anything to protect their domestic producers; even though they don’t have any for 5G. Or if you really like deep dark conspiracies, perhaps the NSA has a backdoor into American Cisco kit and wants to keep its advantage?

The US President’s animosity to trade with China is hardly a secret. Parsimony suggests the rest is fluff.

PHP for C++, C# or Java Programmers

Introduction

Scripting languages are horrible. All of them. However, it is probably true to say that PHP is better than Python, so it’s not all bad. While it shares the latter’s disregard for data types, it does have classes and a full set of statements for structured flow control. Because PHP could run from within Apache, without the overhead of CGI, it gained great popularity for web sites, where “web developers” have committed unspeakable sins against computer science; but it’s not the languages’ fault.

If you’re a C++ programmer, the paragraph above will sound reasonable. If you’re taking issue with my dislike of scripting languages for software engineering, you’re reading the wrong document, because I don’t hold back.

These notes are intended as a quick crib sheet for dealing with PHP for anyone who understands basic C++ or derived languages such as Java and C#), together with Unix scripting. PHP borrows from both. It’d be hard to call yourself a programmer if you didn’t used both, but if you’ve somehow avoided the Bourne (or BASH for penguinistas) you might want to read up on the basics of these first. Whilst the control structures are borrowed from C, the variable and string syntax will be familiar from shell.

This document cuts to the chase – a quick start to PHP for programmers. It’s not a tutorial in how to program for beginners. I come neither to bury nor praise PHP. It has its uses, as do all scripting languages, and can be great fun for a quick lash-up.

Nonsense

Let’s not sugar coat this – there are aspects of PHP that don’t make a lot of sense. Here are a few you should be aware of to avoid a load of confusion:

  • Overloading in PHP does not refer to overloading in anything like the normal sense of the word in computer languages. It’s actually used to talk about interpreter hooks. There is no function overloading in PHP.
  • Case sensitivity is inconsistent. Variable and constant names, and labels, are case sensitive. Other things are not, including function names, class names, keywords and namespaces.
  • PHP syntax isn’t necessarily backward compatible, and new syntax is added on minor versions. This document is based on PHP 7.4, but mentions some important differences with 5.x and 7.x releases.
  • The meaning of “declare” has nothing to do with declaring anything; it sets interpreter options.
  • Multiple inheritance isn’t supported as a matter of design, which is then circumvented using a weird non-class called a trait.
  • The type declaration of “const” does not refer to an immutable object (it’s a way of declaring a manifest constant, and nothing more).
  • Things like parametric polymorphism aren’t supported, but reflection is used to simulate them at run-time.

File format

PHP interprets lines from a text file:

#!/usr/local/bin/php
<!--?php
print (“Hello World\n”);
?-->

Like any other script language, it helps to put the name of the interpreter in the first line of the file although if it’s being run through Apache you won’t need to.

#!/usr/local/bin/php

If you’re using Linux rather than Unix this may be at /bin/php, of course.
Next there is the <!–?php … ?–> business. The PHP interpreter was intended to allow PHP code to be embedded in an HTML tag, so this is the opening and closing of a tag to get it to take notice of the stream.

On later (current) versions you can dispense with the HTML comments and wrap the file in <?php … ?>

And in the middle, there’s our print statement. And it is actually a statement; not a function. I just put the brackets around it because I could. It prints a single string.

Note the semicolon on the end – like ‘C’, line breaks are irrelevant and statements are ended by a ‘;’

PHP also includes the echo statement, which takes multiple arguments like echo in the shell:

echo "foo", "bar";

Having two ways of doing the same thing is all part of the fun on PHP.

Comments

As you might expect from the offspring of C++ and Bourne shell, you can use both types of comment. C++ // and /* */, as well as #. For the sake of sanity, I’ll stick with // in this document, but it’s a matter of taste which you prefer.

Constants

Literal constants follow the conventions you’re used to, with the exception of string literals, which follow normal shell convetions. That’s to say that they may be quoted with either a single (‘) or double (“) quote. A single quote does not produce an integer character code. This is covered in more detail in the Strings section.

Other literal constants are as you’d expect – 123 is a cardinal; 1.23 is a float, and True is a Boolean.

Manifest constants in PHP are, by convention, declared in UPPER CASE, although it doesn’t matter to the language. There are two ways to do it:

const PI = 3.141592;
define ("Euler", 2.71828);

If you redefine a constant PHP will ignore you, silently. In other words, the first definition persists even though this is irrational.

At first sight, define() may look like a pre-processor option, but in an interpreted language this doesn’t really make sense. However, in combination with a conditional, you can use define() to create a constant with a value determined at run-time. The const modifier is a later addition to PHP and works like a compile-time definition (but with no error-checking). It has the advantage that it’s sensitive to namespaces and you’ll probably prefer it going forward. Until PHP 5.3 it only worked in class scope, but this restriction has gone.

It’s widely believed that the initialiser in a const declaration can’t be an expression. It can (since PHP 5.6); it just has to be a constant expression – e.g. const RPI = 1/PI;

Operators

PHP implements the usual operators with the usual precedence, with a few extras.

‘.’ is the string concatenation operator.

‘**’ is the exponential operator (from PHP 5.6 onward).

!== and === differ from != and == in that they must be identical – no type conversions are performed so the expressions being compared must be of the same type to be the same value.

<> is an alternative to !=, although bizarrely it has a precedence one below.

Only a maniac would use this feature in coding.
Comparison operators also work on arrays, and plus (‘+’) can be used to concatenate arrays (i.e. a union operator).

And as of PHP 7, there’s the <=> operator. It returns zero if both arguments are the same, -1 if the left argument is less than the right, and +1 if it’s greater. This is similar to the strcmp() function in the POSIX library, but the thought process that came up with it being a good idea as an operator is baffling.

Variables and Types

All variables are prefixed with a $, whether they appear in an lvalue and as an rvalue (unlike shell). But they don’t have a type.

$a=2;
$b=$a*10;
$a='Twenty: ';
echo $a ,$b;

As you can see, I stored an integer in $a, and then stored a string in it. Variables do have dynamic typing, although at any one time they are of a specific type. There’s a function to return the current type as a string:

$myint=123;
$mystr="A string";
$myreal=3.14159;
$mybool=true;
echo gettype($myint),": ",$myint,"\n";
echo gettype($mystr),": ",$mystr,"\n";
echo gettype($myreal),": ",$myreal,"\n";
echo gettype($mybool),": ",$mybool,"\n";
Output:
integer: 123
string: A string
double: 3.14159
boolean: 1

There are several functions like is_int() for other types, and they return true or false as you’d expect. And speaking of Boolean values, true is the integer 1, whereas false is an empty string. For conditionals, 0 or non-zero work as false or true too; as do empty or non-empty strings.

$a = (3 > 5);
$b = (3 < 5);
print ("a=$a, b=$b");


Output: a=, b=1

Variables in PHP are self-creating on first use, and that includes using them as part of an rvalue. The following nonsense is legal, with $b printing as an empty string. If you’re lucky you’ll get a notice-level warning to alert you to the fact you’ve messed up, but this isn’t guaranteed by any means.

$a="Hello";
echo $a, $b;


Output: Hello

Strings

Numeric expressions work as you’d expect. Strings can be concatenated using the ‘.’ operator (which you should separate with a space. Expression types are cast in a sensible way, so “Testing” . 123; results in a string containing “Testing123”.

$name='Mary';
$day='Monday';
$age=6;
print ("It will be $name's Birthday next $day and she will be $age.\n");

Output: It will be Mary's Birthday next Monday and she will be 6.

As you can see I haven’t quoted the single quote – there’s no need. The usual conventions apply, so to get a double quote you’d need \”. If your variable name isn’t obvious because it has printable characters immediately before or after, put it in curly brackets thus:

{$name}

PHP has dozens of string functions for you to look up, including everyone’s favourite strlen(). Some take the form str_xxx() and some are named strxxx(), for no good reason I can see except for PHP being bonkers.

Arrays

PHP doesn’t go for types, so arrays are also un-typed; and can be of mixed type values. Arrays are also dynamic. In fact they’re really lists, but PHP heads called them arrays anyway.
You can create arrays with an array() function, but the simple way is self-explanatory assuming you’re using a relatively recent version of PHP, as below:

$a1 = []; // Empty array
$a2 = [1,2,3,"Tom","Dick","Harry"]; // Initialised with stuff

If you’re using ancient PHP you could get the equivalent using:

$a1=array();
$a2=array(1,2,3,"Tom","Dick","Harry");

In the above, $a2[3] would be “Tom”, as you might expect. However, PHP arrays only default to zero based integer addressing. The index can be anything else, like a string. (Associative array is a name that may sprint to mind). The full syntax for initialisation is:

 $a3 = [ "red" => "rouge", 
"blue" => "bleu",
"green" => "vert",
"yellow" => "jaune" ];


And $a3[“green”] would return “vert”. You can mix integer indexes in with the strings, and if you don’t specify an index for an element it defaults to the next integer index. That’s to say, the last integer index used plus one. For example the following is perfectly legal, even if it isn’t sane:

$a3 = [ "red" => "rouge",
6 => "bleu",
"green" => "vert",
"jaune" ];


print ("a3[7] = $a3[7] \n");



Output: a3[7] = jaune

Note that this wouldn’t be $a3[8] or $a3[3]; both of which you might expect. This is because the second element had its index set to 6, the third element was given a key and the eight element defaulted to the next integer – 6+1 = 7. $a3[0] won’t get your “rouge”, as it’s got a key instead.

If you’re using an associative array (or integer indexed one), the risk is that PHP will bomb out if it can’t find the index/key. You can avoid this using the array_key_exists() function. It returns a bool and takes two arguments, the first being the key and the second the array. There are a number of array functions similar to those in the STL – in_array(), array_push(), array_pop(), count() sort(), and so on.

To add elements to an array this syntax is:

$a2[] = "Another";
$a3["purple"] = "violet";

The first adds an item indexed by the next available integer index. The second form adds a key/value pair. And yes, if the key or index already exists you’ll over-write the current value with your new one.
To remove an item from an array, you need the unset() function. It basically takes one or more variables or array locations as parameters and removes them, as if they’ve never been set

unset ($a3[6], $a3["green"); // Blue and green should never be seen.

Multi-dimensional array access is the same as for ‘C’ – i.e. as many indexes as you need each in their own square brackets

Flow Control

I hope you had fun with variables and strings. Now we come to some good news. The flow control structures in PHP are the same as ‘C’, Java and C#. Including blocking statements together with curly brackets.

All of the following are valid and work exactly as you’d expect.

if (conditional) statement;

if (conditional) { statement; statement; … }

do statement; while (conditional);

do statement; while (conditional);

while (conditional) statement;

for (initialiser; conditional; increment) statement;

switch (value) // Value can be any type
{
case 1:
statement;
break;
case 2:
statement;

default:
statement;
}

goto label;

There’s also an “enhanced” for loop as in Java, C# or shell script, or the C++ STL:

foreach (array as item) statement;

Basically, each time through the loop the variable “item” is replaced with the next element in “array”.

foreach ($a3 as $element)
print ("The item is $element\n");

Whilst Java omits goto; PHP doesn’t, in common with C, C++ and C#.

In complex code a goto statement can simplify flow control considerably, although it’s hard to come up with a trivial example where it makes sense. Here follows a trivial example where it doesn’t make sense, but you get the idea. Note the label ends in a colon (“:”).

goto mylabel;
print ("This will NOT be printed\n");
mylabel:
print ("Output will start here\n");

Finally, “break” and “continue” work as expected in loops.

In spite of having a full set of structured statements, many PHP developers seem to like using exceptions to implement program flow. More on this later.

Functions/Methods

PHP functions are a simplified version on C/C++/Java/C# syntax. Note that functions are called methods in Java.

So here’s a function:

function square ( $x )
{
return $x * $x;
}

print("2 squared is ".square(2)."\n");

Output: 2 squared is 4

And that’s about it. The keyword “function” tells the interpreter it’s about to get a function definition.

As PHP isn’t typed, there’s no need to worry about specifying a return type, or parameter types. This is probably one of the worst aspects of K&R ‘C’, which was corrected with function prototypes in the ANSI specification. PHP made the same initial mistake, and implemented something similar to function prototypes in PHP version 5 onwards where they were known as type hints. From version 7 they’re called type declarations and have been extended.

Even with type hints, function name overloading isn’t possible; there is no compile-time polymorphism as there is no compilation. However, introspection and reflection are supported in PHP and this is used for un-checked dynamic polymorphic constructs.

The syntax for declaring an (optional) function return type is different to other languages (PHP 7 onward):

function sum($x, $y): float
{
return $x + $y;
}
print("The type of sum() = ".gettype(sum(2,3))."\n");

Output: The type of sum() = double

As you can see, PHP also “rounds up” floats to doubles. The value of return types may be a bit limited, as most of the time dynamic typing will silently convert it to whatever seems right anyway.

In addition to class names, the return type of a function can be one of self (instance of the class the method was defined on), array or callable. From PHP 7 onward you can have book, float, int and string. In 7.2 return types of iterable and object have been added.

The syntax for arguments is the same as C/C++/Java/C#. If you want to use argument type checking, you can write it as:


function square ( int $x )

It’s worth noting that without the optional type checking (which is normal for PHP), a function will return something random if you give it unexpected arguments. There’s a convention that a NULL will be returned in such circumstances, but it’s only a convention.

You can pass by reference by prefixing the variable name with an ampersand “&”, (C++ style).

function square ( &$x )
{
$x = $x*$x;
}

If a function returns a reference, prefix its name with &.

function &add_tax (&$x)
{
$x *= 1.2;
return $x;
}

You can also have default parameter in the same way as C++

function printwhen ( $product, $when="sometime")
{
print ("Your $product will be ready $when.\n");
}

A variable arguments list is accomplished using … as prefix to a variable, which effectively becomes an array of the passed values.

function total (...$numbers)
{
$tot = 0;
foreach ($numbers as $num)
$tot+=$num;
print "The total is $tot\n";
}


total (3,1,4,1,5);
Output: The total is 14

And for one final piece of craziness you can call a function by having its name stored in a string.

function hi()
{
print "Hello\n";
}
$greeting ="hi";
$greeting();

This does not make it a first-class function, or even a pointer to a function. It’s a recipe for disaster.

If you’re wondering about void functions, there’s no such thing, but if you don’t hit a return statement PHP will return a NULL.

Lambda (closure; anonymous) functions are supported:

function myfunction ($a1, $f1)
{
print ("a1=$a1\n");
$f1 (456);
}
myfunction (123, function ($a) { print ("a=$a\n"); } );

This will output

a1=123
a=456

You can make the lambda inherit variables from the local scope with use():

$x = 1; $y = 2;
myfunction (123, function ($a) use ($x, $y) { print ("a=$a, x=$x, y=$y\n"); } );

Output:

a1=123
a=456, x=1, y=2

Just keep reading it until in makes sense.

Classes

The class/object model is pretty much a subset of the same as C++, which has been borrowed by Java and C#. If you’re not used to C++ terminology:

  • method = member function
  • property = member variable = attribute

You define a class using the class keyword followed by the name. The modifiers const, static, public, private and protected have the usual meaning. By default everything is private, but this can be overridden on an element-by-element basis. Unlike C++, you can’t use public:, protected: or private: as labels to change subsequent declarations. There’s no such thing as a “struct” in PHP (which is a class where members default to public, if you’re coming from Java or C#), or a union.

The final keyword can be applied to a class or method, and prevents the class being used as a base for a derived class, or the method being overridden. It’s not the same as Java when it comes to class constants; in PHP use the keyword “const” instead.

A constructor is defined as “public function __construct() …”, with optional arguments. Remember, function name overloading isn’t supported. A class’ destructor is a function named __destruct().

Functions starting with __ (two underscores) are “magic” in PHP. Additional magic functions defined include __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() and __debugInfo(), and might best be described as hooks within a class that get called by the interpreter in particular circumstances. See a PHP reference for further details.

The pseudo-variable $this has the same meaning as other languages. There’s also a keyword “self” (no $) that can be used to refer to the class rather than this particular instantiation (object of class), and “parent”, to refer to the parent class where inheritance is used.

To reference an element within an object of a class, use the arrow operator (“->”), as if it’s a structure pointer dereference in C++. In languages without pointers, like Java and C#, you always use the “.” operator to specify an element, whatever the underlying reality. In ‘C’, the choice of . and -> makes a difference. In PHP, you always use “->”; at least you don’t have to think about it.

So here’s an example, which should be self-explanatory, but I’ll explain it afterwards anyway:

class myClass
{
public $myVar = "My default value";

function printme()
{
print("myVar = " . $this->myVar . "\n");
}
function printhello()
{
print("Hello!\n");
}
}

$myObject = new myClass;
$myObject->printme();

$myObject->myVar = "New value";
$myObject->printme();
myClass::printhello();

Output:

myVar = My default value
myVar = New value
Hello!

First off, note that the attribute $myVar is declared with at $ but this isn’t used when it’s referenced as an element. I’ve made it public so it can be referenced from outside the class.

I haven’t made the printme() method public; it is by default! Inside it I’ve used $this->myVar to get at the attribute. Without the $this-> it won’t be in scope. In other words, properties are NOT in scope of methods.

PHP supports the scope resolution operator “::”, which is used above for the sake of simple demonstration. printhello() is the same as a Class method in Java. Note that myClass::printme(); would fail, because no instantiated object exists for $this to refer to.

The scope resolution becomes important when you use derived classes.

class myChild extends myClass
{
public $childVar = "I'm only a kid";

function printme()
{
myClass::printme();
print("myVar another way = " . $this->myVar . "\n");
print("childVar = " . $this->childVar . "\n");
}
}

$myChildObject = new myChild;
$myChildObject->myVar = "I'm the parent object.";
$myChildObject->printme();

What won’t work is if you have properties of the same name in both the base and derived class. With the auto-creating variables in PHP, “declaring” another myVar in myChild will make it indistinguishable from the same property in myClass. No warning. Just confusion; so take care you never do it. If BOTH properties are private, that’s fine.


class myClass
{
private $myVar = "I'm the parent";
function printme()
{
print("myVar in base = " . $this->myVar . "\n");
}
}

class myChild extends myClass
{
private $myVar = "I'm only a kid";
function printme()
{
myClass::printme();
print("myVar in child = " . $this->myVar . "\n");
}
}

$myObject = new myChild;
$myObject->printme();

Output:

myVar in base = I'm the parent
myVar in child = I'm only a kid

To access a static class property or function (aka attribute or method) prefix it with the class name and the scope resolution operator (not a dot!)
Interface and Abstract Classes

In C++ an interface class contains one or more pure virtual functions (abstract methods) and nothing else. It’s a special case of an abstract class. However, because a class is a class, it’s treated as any other. Multiple inherence lets a new class inherit as from as many parents as it likes; interface or not.

In Java and C#, with single inheritance, multiple interface classes can also be inherited. However, they’re up-front about an interface class, with its own special keyword. PHP shares this, as well as Java’s “implements” keyword when specifying an interface in a class declaration.

Here’s a simple example of an abstract class:

abstract class AbstractClass
{
// Force an extending class to define this method
abstract protected function printme();

// Example method everything will inherent

public function printHello ()
{
print "Hello World\n";
}
}

class ConcreteClass extends AbstractClass
{
public function printme()
{
parent::printHello();
print("I’m concrete\n");
}
}

$rubble = new ConcreteClass;
$rubble->printme();


Output:

Hello World
I’m concrete

If you’re having an interface class (abstract class consisting of only pure virtual functions), in PHP you say so. A concrete class can inherit multiple interfaces (using a comma separated list), even if it can only extend one base class.

interface iPrintable
{
public function printme();
}

interface iFriendly
{
public function printHello();
}

class MyClass implements iPrintable, iFriendly
{
public function printme()
{
print("I’m concrete\n");
}

public function printHello()
{
print("Hi there!\n");
}
}

$myObject = new MyClass;
$myObject->printHello();
$myObject->printme();

Output:

Hi there!
I’m concrete

I’ve previously mentioned that PHP doesn’t support multiple inheritance. To get around this PHP does include something called a trait (from PHP 5.4). If the answer to your problem involves using traits, you’re probably doing something wrong., but you’ll need to be aware of them.

class MyClass
{
public function printHello()
{
print ("Hello");
}
}

trait PrintWorld
{
public function printWorld()
{
print ( " World!\n");
}
}

class Greeting extends MyClass
{
use PrintWorld;
}

$myObject = new Greeting();
$myObject->printHello();
$myObject->printWorld();


Output: Hello World!

As you can see in the code, MyClass and Greeting are both classes. Greeting extends MyClass but uses a trait called PrintWorld. As a result, Greeting inherits the printHello() method from MyClass and the printWorld() method from the PrintWorld trait. You can use as many traits as you like, but there are, unsurprisingly, more limited than a full class. If they have a use, it’s to lump a load of functions together in a convenient place. If you use traits for anything tricky, and need to resolve clashes and work out precedence, you’ll have to read the full manual; and when you do remember it was your fault for getting into the mess in the first place, because I warned you.

Namespace

PHP does support namespaces from PHP 5.3 onward, but it’s clunky. The keyword “namespace” followed by your chosen name must be the first thing in the source file, other than the opening tag (<?php). This is very strict, meaning that you can’t have anything before the tag, including initial html.

Good:

 <?php
namespace Example;

Fatal Error:

 <?php
namespace Example;

Namespaces are hierarchical, and the path can be separated using a backslash (‘\’) – not the scope resolution operator. You can access anything public in a different namespace if you know how to get to it:

namespace test/junk/foo;
\test\junk\somefunction();

You can import classes from another namespace with the “use [… as …]” keyword:

 use \test\junk\myClass as hisClass;

From PHP 5.6 you can also have “use const …” and “use function …”

Reflection and Introspection

Because PHP is interpreted it’s technically possible to mess around with objects at runtime; not the object’s members but the languages’s notion of an object. This can lead you many interesting and amusing problems, but is sometimes the least-worst option for dealing with the fluid object typing inherent in the language.

Let’s be clear here – in assembly language its possible to use self-modifying code. It was clever, and when you had 1K of core to play with, its use was justified. It’s also possible in ‘C’ – you can find the address of a function easily enough and modify the op-codes. However, it’s pretty obvious to anyone that this is a path to madness. And with modern compiler optimisation, wholly unnecessary.

So where you see introspection used sensibly is on checking the arguments to a function. To PHP, every object can look like any other, which appears to be a good reason why parametric polymorphism can’t happen. However, if you write a single function that examines the objects actually passed and acts accordingly.

If you want to read more about this, as ever, the PHP documentation is the place yo go. However, here’s a quick example to give you the idea of how to get started.

class Foo
{
private $my_private_var;
public $my_public_var;
protected $my_protected_var;
function print_my_name ()
{
echo "My name is Foo\n";
$this->my_private_var = "I'm Private";
$this->my_public_var = "I'm Public";
$this->my_protected_var = "I'm Protected";
}
}

// Instantiate a Foo, check it's working and set it's variables.
$test = new Foo;
$test->print_my_name();

// These two functions get the type of a variable
// (in this case it'll be an object) and the class
// name of the object, so your function can decide what
// to do with it.
echo "gettype() returns " . gettype($test) . "\n";
echo "get_class() returns " . get_class($test) . "\n";

// As these next functions are returning arrays, we're going to
// use the print_r() function to print them in readable format
// from now on. And here's where it starts to get silly.

echo "Output of get_object_vars()\n";
print_r(get_object_vars ($test));

echo "\nOutput of get_class_vars()\n";
print_r(get_class_vars ('Foo'));

echo "\nOutput of get_class_methods()\n";
print_r(get_class_methods ('Foo'));

echo "\nOutput after casting object to array\n";
print_r((array)$test);

echo "\nvar_dump() after casting to an array\n";
var_dump((array)$test);

// And now for something really horrible:

$a=(array)$test;
$a["Var_no_one_knows_about"] = "I've got a bad feeling about this.";
$test=$a;

echo "\nThe Foo object after we've hacked it.\n";
print_r((array)$test);

Output

 My name is Foo
gettype() returns object
get_class() returns Foo
Output of get_object_vars()
Array
(
[my_public_var] => I'm Public
)
Output of get_class_vars()
Array
(
[my_public_var] =>
)
Output of get_class_methods()
Array
(
[0] => print_my_name
)
Output after casting object to array
Array
(
[Foomy_private_var] => I'm Private
[my_public_var] => I'm Public
[*my_protected_var] => I'm Protected
)
var_dump() after casting to an array
array(3) {
["Foomy_private_var"]=> string(11) "I'm Private"
["my_public_var"]=> string(10) "I'm Public"
["*my_protected_var"]=> string(13) "I'm Protected"
}
The Foo object after we've hacked it.
Array
(
[Foomy_private_var] => I'm Private
[my_public_var] => I'm Public
[*my_protected_var] => I'm Protected
[Var_no_one_knows_about] => I've got a bad feeling about this.
)

Debugging

There are many PHP functions intended for debugging, but here are a few tips to start you off.

print_r() – Pretty print a variable or array.

var_dump() – As above, but with more information (particularly its type)

debug_zval_dump() – As above, but with reference counts for debugging the PHP interpreter.

Here’s a quick example.

$a = ["One","Two","Three"];
print_r($a);
var_dump($a);

Output

 Array
(
[0] => One
[1] => Two
[2] => Three
)
array(3) {
[0]=> string(3) "One"
[1]=> string(3) "Two"
[2]=> string(5) "Three"
}

One very useful feature of the var_dump() function is that when it’s used for a class it can be overridden by the special “__debugInfo()” member function, which can output the contents in any way you see fit. The default is to dump the lot.

Because debugging is something you’re likely to want to do without wanting to read the whole PHP manual, I’ll go into a bit more detail. These functions will write to the standard output (or HTML stream if you’re using it for a web site). To catch teh output and write it to a file use something like this:

// First we capture the output into an output buffer
// and store the result in the string.
ob_start();
var_dump($a);
$stuff = ob_get_clean();

// Then we append it to a text file of our choice
$fp = fopen("/var/log/mylog.log", "a");
fwrite($fp, $stuff);
fclose($fp);

It’s easier to capture print_r() as it has a default final parameter; a flag to return the output as a string rather than printing it. In this example I’m using the special variable $GLOBALS to dump every global variable.

$stuff = print_r($GLOBALS,true);

Miscellanies

Running shell commands

PHP supports the back-tick operator in the same way as the Bourne shell. Anything between two back-ticks (‘`’) will be passed to the shell, and stdout will replace the whole lot in the interpreted line.

declare()

There’s a keyword “declare” that is akin to a compiler #pragma. It sets various options for the interpreter from this point onward; or for the following block. It doesn’t actually declare anything.

Examples:

 declare (strict_types=1);

This will actually enable type checking on function arguments, assuming someone’s bothered to define types in the first place.

 declare(encoding='ISO-8859-1')
{

}

The code between the { … } is encoded using ‘ISO-8859-1’ (i.e. 8-bit extended ASCII, not Unicode).

include/require

These statements simply include an external file into the interpreter stream at this point.

 include “something.php”;

Require is similar, except it’ll halt execution with a fatal error if the file isn’t found. There are special versions, include_once and require_once, which will refrain from including the named file if it’s been included before.

@ Error control operator

Being an interpreted language, you won’t be bothered by any compile-time errors drawing attention to mistakes in your code. If you want to prevent pesky run-time errors to, you can prefix any expression you like with a commercial at (‘@’), and it’ll suppress any errors or warnings that would otherwise highlight your mistakes. This includes fatal errors, so your script will just stop dead, causing the user to utter many interesting terms of endearment about you when they find out.

As far as I can make out, the @ operator technically sets the run-time error reporting level to zero (that which is returned by error_reporting ()). Any error handlers you’ve set will still be called.

Auto loading functions

PHP programs can become a mess with a lot of includes at the beginning of each script file in order to import a large number of classes. As a result its quite common to use a mechanism called auto-loading. Prior to PHP 8 this was done using a __autoload function() but newer versions use spl_autoload_register() instead.

With __autoload() (two underscores) you basically defined the function and it will be called if some of your code fails with a “Class not found” error. The function takes a class name as its parameter (the one that caused the error) and is likely to include that class from wherever you have it stashed.

This mechanism does, at least, only load classes when they’re first called.

function __autoload($ClassName)
{
    include($ClassName.".php");
}

With PHP 8 it’s a bit more complex. __autoload() has been removed, so you have to use spl_autoload_register() – although you can use this to call an __autoload() from your old code. The difference is that __autoload() has no special meaning any more but it’s still a valid function.

As its name might suggest, it registers a load of autoload functions that the system can use as required.

The function takes the name of an autoload function (which defaults to spl_autoload()) as its first parameter. Two more optional boolean flags are passed – the first can be set to false if you don’t want it to throw an exception, and the second can be set to true if you want the function registered at the front of the list rather than the end.

You’d probably be best reading the full documentation if you come across something that isn’t obvious in the code.

Iteration

Since Version 5, PHP has supported external iterators for arrays objects. There are a couple of dozen predefined, and each of which has a similar number of methods. You’ll have to read the PHP documentation for a comprehensive list. Unfortunately the documentation is lacking for many of them.

Like other languages, an Iterator is an interface that an object may implement. This includes the following methods:

current() – return element pointed to by the cursor.
key() – return the key pointed to by the cursor.
next() – move the cursor on by one.
rewind() move the cursor to the first element.
valid () – return true if the cursor is pointing to a valid element (e.g. it hasn’t gone off the end).

Exception Handling

There really needs to be a section on exception handling. It’s very similar to the Java model, but the way it’s used makes me nauseous and I can’t bring myself to write about it right now.

Jails on FreeBSD are easy without ezjail

I’ve never got the point of ezjail for creating jailed environments (like Solaris Zones) on FreeBSD. It’s easier to do most things manually, and especially since the definitions were removed from rc.conf to their own file, jail.conf. (My biggest problem is remembering whether it’s called “jail” or “jails”!)

jail.conf allows macros, has various macros predefined, and you can set defaults outside of a particular jail definition. If you’re using it as a split-out from rc.conf, you’re missing out.

Here’s an example:

# Set sensible defaults for all jails
path /jail/$name;
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
mount.procfs;
host.hostname $name.my.domain.uk;
# Define our jails
tom { ip4.addr = 192.168.0.2 ; }
dick { ip4.addr = 192.168.0.3 ; }
harry { ip4.addr = 192.168.0.4 ; }
mary { ip4.addr = 192.168.0.5 ; }
alice { ip4.addr = 192.168.0.6 ; }
nagios { ip4.addr = 192.168.0.7 ; allow.raw_sockets = 1 ; }
jane { ip4.addr = 192.168.0.8 ; }
test { ip4.addr = 192.168.0.9 ; }
foo { ip4.addr = 192.168.0.10 ; }
bar { ip4.addr = 192.168.0.11 ; }

So what I’ve done here is set sensible default values. Actually, these are probably mostly set what you want anyway, but as I’m only doing it once, re-defining them explicitly is good documentation.

Next I define the jails I want, over-riding any defaults that are unique to the jail. Now here’s one twist – the $name macro inside the {} is the name of the jail being defined. Thus, inside the definition of the jail I’ve called tom, it defines hostname=tom.my.domain.uk. I use this expansion to define the path to the jail too.

If you want to take it further, if you have your name in DNS (which I usually do) you can set ip.addr= using the generated hostname, leaving each individual jail definition as { ;} !

I’ve set the ipv4 address explicitly, as I use a local vlan for jails, mapping ports as required from external IP addresses if an when required.

Note the definition for the nagios jail; it has the extra allow.raw_sockets = 1 setting. Only nagios needs it.

ZFS and FreeBSD Jails.

The other good wheeze that’s become available since the rise of jails is ZFS. Datasets are the best way to do jails.

First off, create your dataset z/jail. (I use z from my default zpool – why use anything longer, as you’ll be typing it a lot?)

Next create your “master” jail dataset: zfs create z/jail/master

Now set it up as a vanilla jail, as per the handbook (make install into it). Then leave it alone (other than creating a snapshot called “fresh” or similar).

When you want a new jail for something, use the following:

zfs clone z/jail/master@fresh z/jail/alice

And you have a new jail, instantly, called alice – just add an entry as above in jail.conf, and edit rc.conf to configure its networ. And what’s even better, alice doesn’t take up any extra space! Not until you start making changes, anyway.

The biggest change you’re likely to make to alice is building ports. So create another dataset for that: z/jail/alice/usr/ports. Then download the ports tree, build and install your stuff, and when you’re done, zfs destroy
z/jail/alice/usr/ports. The only space your jail takes up are the changes from the base system used by your application. Obviously, if you use python in almost every jail, create a master version with python and clone that for maximum benefit.