Signal drop!
Relay (operand.online) is unreachable.
Usually, a dropped signal means an upgrade is happening. Hold on!
Sorry, no connección.
Hang in there while we get back on track
gram: build
> ./nixos/gram/elixir.nix
Lenses
(coming soon!)
{ channel, base, domain, codebase, name, user, dependencies ? [], app ? name, ... }:
# run_command ? "elixir --erl '-detached' -S mix phx.server",
{ pkgs, edge, ... }:
let
command = call: nd "_build/prod/rel/${app}/bin/${app} ${call}";
cron = "(sh -c 'date -Is' | str trim)";
place = "/home/${user}/run/${name}";
nd = cmd: ''
cd ${place}/run;
if ('flake.nix' | path exists) and ('flake.lock' | path exists) {
print "\n\n(${base})> ${cmd}\n"; nix develop --command ${cmd}
} else { load-env (open ~/gram/${name}.call | lines | split column '=' | transpose -i -r --as-record); ${cmd} }
'';
nd-place = node: cmd: nd ''cd ${node}; ${cmd}'';
nu = name: body: pkgs.writeScriptBin name ''
#!${edge.nushell}/bin/nu
${body}
'';
error = pkgs.writeText "error.html" ''
<style>
body { color: #00aa66; background-color: #003366; }
html, body { height: 100vh; width: 100vw; }
a, a:visited { color: #00aa66; }
</style>
<h1>oooops;<br/>s-lip.</h1>
<span>⡢ ⡢ ⡢ <br/><br/>
learn braille, use
<a href="https://www.unicode.org/charts/nameslist/c_2800.html">://unicode.org</a><br/>
</span>
'';
measures = {
clone = ''
let source = $"${place}/${cron}"; mkdir ${place}
${pkgs.git}/bin/git clone ${codebase} $source
if ("~/share/gram/${name}/share" | path exists) {
${pkgs.rsync}/bin/rsync -a ~/share/gram/${name}/share $source
} else { mkdir ([$source share ] | path join)}
# let node = (ls ($source | into glob)).name.0
# tree -dafix --noreport $node | lines | each {|n| try { chmod 777 $n } }
try { ${pkgs.rsync}/bin/rsync -a ${place}/run/_build $source }
try { rm ${place}/run }; ln -s $source ${place}/run
mkdir ${place}/deps
mkdir ${place}/node_modules
try { cp /home/${user}/gram/${name}.call ${place}/run/.call }
chmod 765 ${place}/run/assets/
ln -s ${place}/deps ${place}/run/deps
ln -s ${place}/node_modules ${place}/run/assets/node_modules
if ("${place}/run/static/assets/" | path exists) {
chmod -R 765 ${place}/run/static/assets/ }
'';
prepare = ''
${nd "mix deps.get"}
# ...
if ("${place}/run/assets/yarn.lock" | path exists) {
chmod 664 ${place}/run/assets/yarn.lock
${nd "yarn --cwd assets install --production"}
chmod 664 ${place}/run/assets/yarn.lock
}
tree -afix --noreport ${place}/run/priv/static | lines | where { ($in | path type) == file } | each { chmod 664 $in }
${nd "mix setup"}
'';
spinup = ''
if ("${place}/run/assets/yarn.lock" | path exists) {
chmod 664 ${place}/run/assets/yarn.lock
${nd "yarn --cwd assets install --production"}
chmod 664 ${place}/run/assets/yarn.lock
}
tree -afix --noreport ${place}/run/priv/static | lines | where { ($in | path type) == file } | each { chmod 664 $in }
${nd "mix assets.build"}
'';
spin = with measures; ''
${clone}
${spinup}
${close}
${command "daemon"}
'';
run = with measures; ''
${clone}
${prepare}
${cycle}
'';
cycle = with measures; ''
${nd "mix release"}
${close}
${command "daemon"}
'';
close = "try { ${close_channel channel} }";
do = ''
def main --wrapped [ ...call: string ] {
${command "...($call)"}
}'';
};
# mix = nu "mix-${name}" ''
# ${nd "mix ...($call)"}
# '';
# ${nd "mix phx.gen.release"}
# ${nd "print $env"}
# ${nd run_command}
# nd "${command} daemon"
# nd "${command} daemon_iex"
# try { ${close_channel channel} }
close_channel = channel: ''
let process = (
netstat -tunlp | tail -n+3 | lines |
split column -r ' +' |
where column7 =~ $"/("beam")" |
where column4 =~ ":${toString channel}" |
get column7 | split row "/" | get 0 | into int
); kill $process
'';
in {
environment.systemPackages = with pkgs; with measures; [
(nu "run-${name}" run)
(nu "spin-${name}" spin)
(nu "do-${name}" do)
(nu "close-${name}" close)
(nu "cycle-${name}" cycle)
(nu "prepare-${name}" prepare)
# (nu "release-${name}" release)
] ++ dependencies; networking.firewall.allowedTCPPorts = [ 80 443 channel ];
imports = [(import ../module/proxy.nix { inherit name domain channel; lines = ''
handle_errors {
rewrite * ${error}
file_server
} '';
})];
services.postgresql = {
enable = true; enableTCPIP = true; settings.port = 5432;
ensureDatabases = [ name ];
authentication = pkgs.lib.mkOverride 10 ''
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
'';
};
# systemd.services."${name}@elixir" = {
# enable = false;
# description = "${name}, running locally on :${toString channel} and securely proxied on ${domain}";
# wantedBy = ["multi-user.target"];
# unitConfig = { After = "local-fs.target"; Wants = "local-fs.target"; };
# environment = {
# PHX_HOST = domain; DATABASE_URL = "postgres://postgres@127.0.0.1:5432/${name}";
# PORT = toString channel; MIX_ENV = "prod"; PHX_SERVER = "y";
# HOME = "/home/${user}/run"; NO_VHOST = "0";
# };
# # environment.PATH = lib.mkForce "/run/current-system/sw/bin/";
# serviceConfig = { Type = "forking"; KillMode = "mixed"; TimeoutSec = 0;
# ExecStart = "${run}/bin/run-${name}"; };
# };
}