summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2022-05-24 18:21:20 -0400
committerBen Sima <ben@bsima.me>2022-07-05 19:02:07 -0400
commitb72f6ba9f7a6987f184ac510491e452c3ea855b1 (patch)
tree201e1bd8d533f99fffceba6ba7310b29308160d5
parent98963d27e5d6ed7327846471d791bcdcb9eb58b4 (diff)
Init urbit harbor
This is mostly stubbed out and needs some work to be functional... the idea is to run urbit ships as systemd services, and provide a simple interface for managing them.
-rw-r--r--Urbit/Cloud.hs16
-rw-r--r--Urbit/Harbor.hs39
-rw-r--r--Urbit/Harbor.nix98
-rw-r--r--Urbit/Ship.nix44
4 files changed, 197 insertions, 0 deletions
diff --git a/Urbit/Cloud.hs b/Urbit/Cloud.hs
new file mode 100644
index 0000000..8e7fb89
--- /dev/null
+++ b/Urbit/Cloud.hs
@@ -0,0 +1,16 @@
+-- | Urbit Cloud is a frontend for managing a fleet of hosted Urbit ship.
+--
+-- Features:
+--
+-- * frontpage advert
+--
+-- * signup, login, monthly payments
+--
+-- * dashboard to see your running ships, reset +code, etc
+--
+-- * manage your resource usage (at extra cost)
+--
+-- * admin dashboard to see all ship statuses and statistics
+module Urbit.Cloud where
+
+main = undefined
diff --git a/Urbit/Harbor.hs b/Urbit/Harbor.hs
new file mode 100644
index 0000000..d95f1a0
--- /dev/null
+++ b/Urbit/Harbor.hs
@@ -0,0 +1,39 @@
+{-
+
+Urbit Harbor is a supervisor for Urbit ships on the local machine. It does no
+orchestration, it just manages systemd services.
+
+Plan:
+ - make this run 10 fake galaxies
+ - make this run 100 fake ships
+
+- Requirements:
+ - setup new ship
+
+Setup process:
+
+ <running as user "urbit-harbor">
+ dir=/var/urbit/harbor
+ urbit -c $dir/zod -k $dir/zod.key -x # one-time setup
+ <create $dir/zod.service from some template>
+ systemctl --user enable $dir/zod.service # nees fullpath
+ systemctl --user start zod.service
+
+Service Template:
+
+ [Service]
+ ExecStart=urbit -tq /var/urbit/harbor/zod # maybe want -d?
+ ExecStartPre=mkdir -p /var/urbit/harbor/zod
+
+ [Unit]
+ Description=zod
+
+ [Install]
+ WantedBy=multi-user.target
+
+TODO:
+ - use systemd.resource-control to limit memory/CPU for ships
+ - Urbit.Cloud controller will set different limits by reading/editing the
+ ini file, and change price to customer
+ - figure out what firewall stuff i need to do
+-}
diff --git a/Urbit/Harbor.nix b/Urbit/Harbor.nix
new file mode 100644
index 0000000..72507d0
--- /dev/null
+++ b/Urbit/Harbor.nix
@@ -0,0 +1,98 @@
+{ options
+, lib
+, config
+, pkgs
+, ...
+}:
+
+/*
+
+Urbit Harbor is a supervisor for Urbit ships on the local machine. It does no
+orchestration, it just manages systemd services.
+
+Setup process:
+
+ <running as user "urbit-harbor">
+ dir=/var/urbit/harbor
+ urbit -c $dir/zod -k $dir/zod.key -x # one-time setup
+ <create $dir/zod.service from some template>
+ systemctl --user enable $dir/zod.service # nees fullpath
+ systemctl --user start zod.service
+
+
+Service Template:
+
+ [Service]
+ ExecStart=urbit -tq /var/urbit/harbor/zod # maybe want -d?
+ ExecStartPre=mkdir -p /var/urbit/harbor/zod
+
+ [Unit]
+ Description=zod
+
+ [Install]
+ WantedBy=multi-user.target
+
+
+TODO:
+ - use systemd.resource-control to limit memory/CPU for ships
+ - Urbit.Cloud controller will set different limits by reading/editing the
+ ini file, and change price to customer
+ - figure out what firewall stuff i need to do
+*/
+
+let
+ cfg = config.services.urbit-harbor;
+in {
+ options.services.urbitharbor = {
+ enable = lib.mkEnableOption "Enable urbit-harbor";
+
+ dataDir = lib.mkOption {
+ type = lib.types.path;
+ default = "/var/urbit/harbor";
+ description = "Where to store piers";
+ };
+
+ ships = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ description = "List of @p's to start up, without the leading ~";
+ };
+
+ package = lib.mkOption {
+ type = lib.types.package;
+ default = pkgs.urbit-harbor;
+ description = "The urbit-harbor package to use";
+ };
+
+ urbitPackage = lib.mkOption {
+ type = lib.types.package;
+ default = pkgs.urbit;
+ description = "The urbit package to use";
+ };
+
+ user = lib.mkOption {
+ type = lib.types.user;
+ default = "urbit-harbor";
+ description = "User to run as";
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ systemd.services.urbit-harbor = {
+ path = [ cfg.package cfg.urbitPackage ];
+ wantedBy = [ "multi-user.target" ];
+ preStart = ''
+ mkdir -p ${cfg.dataDir}
+ '';
+ script = "${cfg.package}/bin/urbit-harbor ${cfg.dataDir}";
+ description = "Urbit harbor";
+ serviceConfig = {
+ User = cfg.user;
+ Type = "simple";
+ Restart = "always";
+ RestartSec = "3";
+ };
+ };
+
+ };
+
+}
diff --git a/Urbit/Ship.nix b/Urbit/Ship.nix
new file mode 100644
index 0000000..ec6a9ec
--- /dev/null
+++ b/Urbit/Ship.nix
@@ -0,0 +1,44 @@
+{ bild ? import ../Biz/Bild.nix {}
+}:
+
+# This represents a single ship running in a container.
+
+let
+ # bootstrap & startup process, expects two files:
+ # - /ship.name: containing a ship name like 'sampel-palnet'
+ # - /ship.key: containing the key
+ urbit-start = bild.pkgs.writeScript "urbit-start" ''
+ #!${bild.pkgs.runtimeShell}
+ set -xeuo pipefail
+
+ ship=$(cat /ship.name)
+ pier="/$ship"
+
+ if [ -d "$pier" ]; then
+ # pack pier if it exists, to save space
+ /bin/urbit-worker pack "$pier"
+ else
+ # otherwise, setup
+ /bin/urbit -c "$pier" -k /ship.key -x
+ fi
+
+ /bin/urbit -tq "$pier"
+ '';
+in bild.image {
+ name = "urbit-ship";
+ tag = "latest";
+
+ fromImage = null; # scratch
+
+ contents = bild.pkgs.urbit;
+
+ config = {
+ Cmd = [
+ "${urbit-start}"
+ ];
+ WorkingDir = "/";
+ Volumes = {
+ "/" = { };
+ };
+ };
+}