#!/usr/bin/perl

use strict;
use warnings;

system("touch /etc/systemd/dont-synthesize-nobody") if -d "/etc/systemd";
my $uid = getpwnam("nobody");
my $gid = getgrnam("nobody");
my @ids = ( 65534, 99 );

my $user_needs_informed = 0;

if ( !defined $gid ) {
    $user_needs_informed = 1;

    my $addgroup = -x '/usr/sbin/groupadd' ? "groupadd" : "addgroup";
    for my $id (@ids) {
        system("$addgroup --system --gid $id nobody");
        $gid = getgrnam("nobody");
        last if defined $gid;
    }

    if ( !defined $gid ) {
        system("$addgroup --system nobody");
    }

    $gid = getgrnam("nobody");
    die "Could not ensure `nobody` group\n" if !defined $gid;
}

if ( !defined $uid ) {
    $user_needs_informed = 1;

    my $flags = -x '/usr/sbin/groupadd' ? "" : "--disabled-password --disabled-login";
    for my $id (@ids) {
        system("adduser --system --uid $id --gid $gid --home / --no-create-home --shell /sbin/nologin $flags nobody");
        $uid = getpwnam("nobody");
        last if defined $uid;
    }

    if ( !defined $uid ) {
        system("adduser --system --gid $gid --home / --no-create-home --shell /sbin/nologin $flags nobody");
    }

    $uid = getpwnam("nobody");
    die "Could not ensure `nobody` user\n" if !defined $uid;
}

# if already done, its a noop. adduser’s --gid does not make this happen
system("usermod -g $gid nobody");

my $home = ( getpwnam("nobody") )[7];
if ( !-d $home ) {

    # We do not want to create it for them in case there are other implications in /nonexistent existing.
    # We can’t `usermod --home / nobody` for them because we’d have to hard stop all nobody processes first.
    my $sep = "#" x 42;
    print <<"END_HOMEDIR";
$sep
[WARN] Detected non-existent home directory for `nobody`.

This situation can result in some harmless STDERR going to your web server’s error log as errors.

If you experience this your options are:

  1. Ignore the log entries
  2. Create the directory “$home” if it is safe to do so.
  3. Change the `nobody` user’s home directory to one that exists. e.g. `usermod --home / nobody`
$sep
END_HOMEDIR

}

print "[INFO] `nobody` user created with UID $uid and GID $gid\n" if $user_needs_informed;
