Commit Diff


commit - /dev/null
commit + b2a430be86f34ed6d6fa5170b3684fec425462be
blob - /dev/null
blob + 8330245a806e72eaff002942114083495ca7f4da (mode 644)
--- /dev/null
+++ dhcpd.conf
@@ -0,0 +1,17 @@
+shared-network host-lec {
+	subnet 38.81.163.14 netmask 255.255.255.255 {
+	}
+	subnet 38.87.162.0 netmask 255.255.255.0 {
+	        range 38.87.162.80 38.87.162.119;
+	        option routers 38.87.162.1;
+		option domain-name "host.lecturify.net";
+	        option domain-name-servers 38.81.163.14;
+		next-server host.lecturify.net;
+		filename "auto_install";
+		use-host-decl-names on;
+	        host username.host.lecturify.net {
+	                fixed-address 38.87.162.245;
+	                hardware ethernet aa:bb:cc:dd:ee:ff;
+	        }
+	}
+}
blob - /dev/null
blob + c619f1f2a13b74018c9028d244b26238b966ff59 (mode 644)
--- /dev/null
+++ mailtemplate
@@ -0,0 +1,38 @@
+Greetings $username,
+
+We are glad to have you join. Here are the training docs:
+
+https://wiki.ircnow.org/?n=Minutemin.Bootcamp
+
+We ask every teammate to hang out with us on $ircserver
+port 6667 for plaintext, port 6697 for SSL. Please join $ircchannel
+We can help you there with tech support. You can also sign up
+to our mailing list at training+subscribe@ircnow.org.
+
+The free sysadmin course will last for one month.
+We hope you'll enjoy hanging out with our community.
+
+You are welcome to use the VPS for personal experiments after training,
+but you must follow our terms of service:
+
+https://wiki.ircnow.org/?n=Terms.Vps
+
+Username: $username
+Password: $password
+Hostname: $username.$hostname
+IPv4: $ipv4
+IPv6: $ipv6/64
+IPv4 Default Gateway: 38.87.162.1
+IPv6 Default Gateway: 2602:fccf:1::1
+Routing Prefix Length: 48
+Port: 22
+
+Your root password is the same as your user password.
+
+After you log in, you can change your password by typing:
+
+$ passwd $username
+
+$sshfingerprints
+
+IRCNow
blob - /dev/null
blob + a99e738d6234fbc2e1592f83798f1a27b37e307b (mode 755)
--- /dev/null
+++ ssh
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# Read from filename and return array of lines without trailing newlines
+sub readarray {
+	my ($filename) = @_;
+	open(my $fh, '<', $filename) or die "Could not read file '$filename' $!";
+	chomp(my @lines = <$fh>);
+	close $fh;
+	return @lines;
+}
+
+# Read from filename and return as string
+sub readstr {
+	my ($filename) = @_;
+	open my $fh, '<', $filename or die "Could not read file '$filename' $!";
+	my $str = do { local $/; <$fh> };
+	close $fh;
+	return $str;
+}
+my $username = "jrmu";
+my $password = "TrophyCantaloupeWaterfall";
+my $server = "host.lecturify.net";
+my $ircserver = "irc.lecturify.net";
+my $ircchannel = "#wheel";
+my $ip4 = "38.87.162.96";
+my $ip6 = "2602:fccf:1:1096::";
+my $sshfingerprints =
+"ssh-keygen -E md5 -lf /etc/ssh/ssh_host_dsa_key.pub
+ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ecdsa_key.pub
+ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ed25519_key.pub
+ssh-keygen -E md5 -lf /etc/ssh/ssh_host_rsa_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_dsa_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub";
+
+foreach my $line (readarray("vpses")) {
+	if ($line =~ /^(.*) (.*)$/) {
+		print "\$ ssh $1\@$1.$server , password $2\n";
+	}
+}
+my $line = readstr("mailtemplate");
+$line =~ s/\$USERNAME/$username/g;
+$line =~ s/\$PASSWORD/$password/g;
+$line =~ s/\$SERVER/$server/g;
+$line =~ s/\$IRCSERVER/$ircserver/g;
+$line =~ s/\$IRCCHANNEL/$ircchannel/g;
+$line =~ s/\$IP4/$ip4/g;
+$line =~ s/\$IP6/$ip6/g;
+$line =~ s/\$SSHFINGERPRINTS/$sshfingerprints/g;
+print $line;
blob - /dev/null
blob + f411fbb1c2ecf9d1d716e86c2dfca5fe58881369 (mode 755)
--- /dev/null
+++ vmmmgr
@@ -0,0 +1,250 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use OpenBSD::Pledge;
+use OpenBSD::Unveil;
+#use Data::Dumper;
+use File::Copy qw(copy);
+use Getopt::Std;
+
+my $vmconfpath = "/etc/vm.conf";
+my $zonedir = "/var/nsd/zones/master/";
+my $hostname = "host.lecturify.net";
+my $ipv4path = "/etc/ipv4s";
+my $isopath = "/home/iso/install73.iso";
+
+# Read from filename and return array of lines without trailing newlines
+sub readarray {
+	my ($filename) = @_;
+	open(my $fh, '<', $filename) or die "Could not read file '$filename' $!";
+	chomp(my @lines = <$fh>);
+	close $fh;
+	return @lines;
+}
+
+# Read from filename and return as string
+sub readstr {
+	my ($filename) = @_;
+	open my $fh, '<', $filename or die "Could not read file '$filename' $!";
+	my $str = do { local $/; <$fh> };
+	close $fh;
+	return $str;
+}
+
+# Write str to filename
+sub writefile {
+	my ($filename, $str) = @_;
+	open(my $fh, '>', "$filename") or die "Could not write to $filename";
+	print $fh $str;
+	close $fh;
+}
+
+# Append str to filename
+sub appendfile {
+	my ($filename, $str) = @_;
+	open(my $fh, '>>', "$filename") or die "Could not append to $filename";
+	print $fh $str;
+	close $fh;
+}
+
+sub date {
+	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
+	my $localtime = sprintf("%04d%02d%02d", $year+1900, $mon+1, $mday);
+	return $localtime;
+}
+
+# Create DNS RR given name, TTL, record type, and value
+sub setdns {
+	my ($name, $ttl, $rr, $value) = @_;
+	my $zonepath = "$zonedir/$hostname";
+	`doas chmod -R g+w $zonedir`;
+	my @lines = readarray($zonepath);
+	foreach my $line (@lines) {
+		# increment the zone's serial number
+		if ($line =~ /(\d{8})(\d{2})((\s+\d+){4}\s*\))/) {
+			my $date = date();
+			my $serial = 0;
+			if ($date <= $1) { $serial = $2+1; }
+			$line = $`.$date.sprintf("%02d",$serial).$3.$';
+		}
+	}
+	push(@lines, "$name        $ttl    IN      $rr       $value");
+	# trailing newline necessary
+	writefile("$zonepath.bak", join("\n", @lines)."\n");
+	copy "$zonepath.bak", $zonepath;
+	if (system("doas -u _nsd nsd-control reload")) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+# Return the next IPv4 address and update ipv4path
+
+sub nextipv4 {
+	my @ipv4s;
+	if (!(-s "$ipv4path")) {
+		print "No IPv4 addresses in $ipv4path!\n";
+		die;
+	} else {
+		@ipv4s = readarray($ipv4path);
+	}
+	my $ipv4 = shift(@ipv4s);
+	system "doas chmod g+w $ipv4path";
+	writefile($ipv4path, join("\n", @ipv4s));
+	return $ipv4;
+}
+
+sub ipv6fromipv4 {
+	my ($ipv4) = @_;
+	if ($ipv4 =~ /^[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+)$/) {
+		return "2602:fccf:1:1".sprintf("%03d",$1)."::";
+	}
+}
+
+sub deletedns {
+	my ($username) = @_;
+	my $filename = "$zonedir/$hostname";
+	`doas chmod -R g+w $zonedir`;
+        my @buf = grep(!/^;?(ns[0-9]\.)?$username\s/, readarray($filename));
+	writefile("${filename}.bak", join("\n", @buf)."\n");
+	copy "${filename}.bak", "$filename";
+}
+
+sub createvm {
+        my ($username, $password) = @_;
+	print "Username: $username\n";
+	print "Password: $password\n";
+        system "doas groupadd $username";
+        system "doas adduser -batch $username $username $username `encrypt $password`";
+        system "doas usermod -G vmdusers $username";
+        system "doas chmod -R o-rwx /home/$username";
+        system "doas ln -s $isopath /home/$username/$username.iso";
+        system "doas su -l $username -c \"vmctl create -s 20G $username.qcow2\"";
+	print "VM created for $username!\n";
+	my @vmconf = readarray($vmconfpath);
+	my $lladdr;
+	foreach my $line (@vmconf) {
+		if ($line =~ /lladdr (.*)/) {
+			$lladdr = $1;
+		}
+	}
+	if (defined($lladdr) && $lladdr =~ /([0-9a-fA-F]{2})$/) {
+		$lladdr = $`.($1+1);
+	}
+	my $block = <<"EOF";
+vm "$username" {
+	owner $username
+	memory 1024M
+	cdrom "/home/$username/$username.iso"
+	disk /home/$username/$username.qcow2
+	interface {
+		locked lladdr $lladdr
+		switch "switch0"
+	}
+}
+EOF
+	appendfile($vmconfpath, $block);
+	`doas vmctl reload`;
+}
+
+sub createconf {
+        my ($username, $password, $ipv4, $ipv6) = @_;
+	my $block = readstr("vmmmgr.conf");
+	$block =~ s/\$password/$password/g;
+	$block =~ s/\$username/$username/g;
+	$block =~ s/\$ipv4/$ipv4/g;
+	$block =~ s/\$ipv6/$ipv6/g;
+	writefile("/var/www/htdocs/$username-install.conf", "$block");
+}
+
+sub deletevm {
+	my ($username) = @_;
+	print "$username deleted";
+	my $buf = readstr($vmconfpath);
+	my $vmconf;
+	if ($buf =~ /vm "$username" \{.*\n\}/s) {
+		$vmconf = $`.$';
+		print $vmconf;
+	}
+	system "doas vmctl stop $username";
+	system "doas userdel -r $username";
+	system "doas groupdel $username";
+	system("doas touch ${vmconfpath}.bak");
+	system("doas chmod g+w ${vmconfpath}.bak");
+	writefile("${vmconfpath}.bak", "$vmconf");
+	copy "${vmconfpath}.bak", "$vmconfpath";
+	print "VM deleted for $username!\n";
+	system "doas vmctl reload";
+}
+
+sub mail {
+	my ($username, $password, $ipv4, $ipv6) = @_;
+my $ircserver = "irc.lecturify.net";
+my $ircchannel = "#wheel";
+my $fromname = 'jrmu';
+my $from = 'jrmu@ircnow.org';
+my $sshfingerprints =
+"ssh-keygen -E md5 -lf /etc/ssh/ssh_host_dsa_key.pub
+ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ecdsa_key.pub
+ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ed25519_key.pub
+ssh-keygen -E md5 -lf /etc/ssh/ssh_host_rsa_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_dsa_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
+ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub";
+
+foreach my $line (readarray("vpses")) {
+	if ($line =~ /^(.*) (.*)$/) {
+		print "\$ ssh $1\@$1.$hostname , password $2\n";
+	}
+}
+my $line = readstr("mailtemplate");
+$line =~ s/\$username/$username/g;
+$line =~ s/\$password/$password/g;
+$line =~ s/\$hostname/$hostname/g;
+$line =~ s/\$ircserver/$ircserver/g;
+$line =~ s/\$ircchannel/$ircchannel/g;
+$line =~ s/\$ipv4/$ipv4/g;
+$line =~ s/\$ipv6/$ipv6/g;
+$line =~ s/\$sshfingerprints/$sshfingerprints/g;
+	open(my $fh, "| /usr/sbin/sendmail -tv -F '$fromname' -f $from") or die "Could not send mail $!";
+	print $fh $line;
+	close $fh;
+	return "true";
+}
+
+my %opts;
+getopts('hid', \%opts);
+if (defined($opts{i})) {
+	print "Username: ";
+	chomp(my $username = <STDIN>);
+	print "Password: ";
+	chomp (my $password = <STDIN>);
+	print "IPv4: ";
+	chomp (my $ipv4 = <STDIN>);
+	$ipv4 = $ipv4 // nextipv4();
+	print "IPv6: ";
+	chomp (my $ipv6 = <STDIN>);
+	$ipv6 = $ipv6 // ipv6fromipv4($ipv4);
+	setdns($username, "3600", "A", $ipv4);
+	setdns($username, "3600", "AAAA", $ipv6);
+	setdns("ns1.$username", "3600", "A", $ipv4);
+	setdns("ns2.$username", "3600", "A", $ipv4);
+	setdns(";$username", "3600", "NS", "ns1.$username");
+	setdns(";$username", "3600", "NS", "ns2.$username");
+	if (system("./vmmmgr-get-sets")) { # return >0 on error
+		die "OpenBSD installation sets corrupt";
+	} else { # return 0 on success
+		createvm($username, $password);
+		createconf($username, $password, $ipv4, $ipv6);
+	}
+} elsif (defined($opts{d})) {
+	print "Username: ";
+	chomp(my $username = <STDIN>);
+	deletevm($username);
+	deletedns($username);
+} else {
+	print "Usage: vmmmgr -dhi\n"
+}
blob - /dev/null
blob + 16a6ef6643bd810c04a2998375253a3ac5745f20 (mode 755)
--- /dev/null
+++ vmmmgr-get-sets
@@ -0,0 +1,22 @@
+MIRROR="https://mirror.esc7.net/pub/OpenBSD"
+doas mkdir -p /var/www/htdocs/pub/OpenBSD/$(uname -r)/$(uname -p)/
+doas chown -R :wheel /var/www/htdocs/pub
+doas chmod -R g+w /var/www/htdocs/pub
+cd /var/www/htdocs/pub/OpenBSD/$(uname -r)/$(uname -p)/
+for file in BOOTIA32.EFI BOOTX64.EFI BUILDINFO INSTALL.amd64 SHA256 SHA256.sig base71.tgz bsd bsd.mp bsd.rd cd71.iso cdboot cdbr comp71.tgz floppy71.img game71.tgz index.txt install71.img install71.iso man71.tgz miniroot71.img pxeboot xbase71.tgz xfont71.tgz xserv71.tgz xshare71.tgz
+do
+	if [[ ! -r $file ]]; then
+	        ftp $MIRROR/$(uname -r)/$(uname -m)/$file
+	fi
+done
+
+signify -C -p /etc/signify/openbsd-$(uname -r | tr -d '.')-base.pub -x SHA256.sig
+cat > install.site << EOF
+echo "@reboot /usr/bin/tmux new -d 'while true; do /sbin/ping -i5 38.87.162.1; done' \;" >> /var/cron/tabs/root
+echo $MIRROR > /etc/installurl
+EOF
+chmod ug+x install.site
+doas chown root:wheel install.site
+doas tar -cvzf site71.tgz install.site
+doas rm install.site
+doas ls -lT > index.txt
blob - /dev/null
blob + 284342161f530860bc94f09726f60e06b9dc2c43 (mode 644)
--- /dev/null
+++ vmmmgr.conf
@@ -0,0 +1,18 @@
+System hostname = $username
+IPv4 address for vio0 = $ipv4
+IPv6 address for vio0 = $ipv6
+Default IPv4 route = 38.87.162.1
+IPv6 default router = 2602:fccf:1::1
+IPv6 prefix length for vio0 = 48
+DNS domain name = host.lecturify.net
+DNS nameservers = 38.81.163.14
+Password for root = $password
+Setup a user = $username
+Password for user = $password
+What timezone are you in = US/Central
+Location of sets = http
+HTTP Server = $hostname
+Server directory = pub/OpenBSD/7.1/amd64
+Set name(s) = bsd comp71.tgz xbase71.tgz xserv71.tgz bsd.rd man71.tgz xshare71.tgz site71.tgz base71.tgz game71.tgz xfont71.tgz
+Continue anyway = yes
+Continue without verification = yes
blob - /dev/null
blob + 284342161f530860bc94f09726f60e06b9dc2c43 (mode 644)
--- /dev/null
+++ vmmmgr.conf.tmpl
@@ -0,0 +1,18 @@
+System hostname = $username
+IPv4 address for vio0 = $ipv4
+IPv6 address for vio0 = $ipv6
+Default IPv4 route = 38.87.162.1
+IPv6 default router = 2602:fccf:1::1
+IPv6 prefix length for vio0 = 48
+DNS domain name = host.lecturify.net
+DNS nameservers = 38.81.163.14
+Password for root = $password
+Setup a user = $username
+Password for user = $password
+What timezone are you in = US/Central
+Location of sets = http
+HTTP Server = $hostname
+Server directory = pub/OpenBSD/7.1/amd64
+Set name(s) = bsd comp71.tgz xbase71.tgz xserv71.tgz bsd.rd man71.tgz xshare71.tgz site71.tgz base71.tgz game71.tgz xfont71.tgz
+Continue anyway = yes
+Continue without verification = yes
blob - /dev/null
blob + f8534d08f1e7f750f617d9bb928c8c8949b285c8 (mode 644)
--- /dev/null
+++ vpses
@@ -0,0 +1,4 @@
+freepress
+BeaconOfLiberty
+38.87.162.95
+2602:fccf:1:1095::
blob - /dev/null
blob + c21a572deae0dfa0ab93df29d6207ba9f1ce6548 (mode 644)
--- /dev/null
+++ vpses.orig
@@ -0,0 +1,5 @@
+freepress BeaconOfLiberty
+independence NetworkDeclaration
+billofrights ChecksAndBalances
+netizen TownHall
+democracy ConceivedInLiberty