Skip to content

Instantly share code, notes, and snippets.

@DeedleFake
Last active April 26, 2024 18:45
Show Gist options
  • Save DeedleFake/19247c95171be2a511de31e17b5e652d to your computer and use it in GitHub Desktop.
Save DeedleFake/19247c95171be2a511de31e17b5e652d to your computer and use it in GitHub Desktop.
Livebook Setup with livebook:// URL Support on Linux

A Quick Guide to Setting up Livebook with Support for livebook:// URLs on Linux

Note that the following steps are intended as a rough outline. They are exact steps to replicate my setup, but your setup might differ depending on, for example, using an init system other than systemd or various other factors. Adjust as necessary.

  1. Run docker volume create livebook-data and docker volume create livebook-config.
  2. Place the livebook.service file in $HOME/.config/systemd/user.
  3. Run systemctl --user enable --now livebook.service.
  4. Place the dev.livebook.Livebook.desktop file in $HOME/.local/share/applications.
  5. Place the dev.livebook.Livebook.svg file in $HOME/.local/share/icons/hicolor/scalable/apps.
  6. Place the livebook file somewhere in your $PATH. In my case, I put it in $HOME/.local/bin.
  7. Run chmod a+x <path to file from step 6>.
  8. Run xdg-mime default dev.livebook.Livebook.desktop x-scheme-handler/livebook.
  9. Place the livebook-daemon file somewhere. I put it in my path, but it doesn't have to be.
  10. Run chmod a+x <path to file from step 9>.
  11. Modify livebook.service so that the ExecStart= line has the absolute path to the location of livebook-daemon.

Voila. livebook:// URLs should now work.

[Desktop Entry]
Type=Application
Name=Livebook
Exec=livebook %u
Icon=dev.livebook.Livebook
StartupNotify=false
MimeType=x-scheme-handler/livebook;
Display the source blob
Display the rendered blob
Raw
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" id="svg2" xml:space="preserve" width="823.87854" height="901.65137" viewBox="0 0 823.87854 901.65133" sodipodi:docname="logo.svg" inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<metadata id="metadata8">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs6">
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath20">
<path d="M 0,805.333 H 3800 V 0 H 0 Z" id="path18" />
</clipPath>
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath148">
<path d="M 353.619,544.464 H 573.136 V 440.053 H 353.619 Z" id="path146" />
</clipPath>
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath172">
<path d="m 351.9,352.883 h 95.147 V 122.614 H 351.9 Z" id="path170" />
</clipPath>
</defs>
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="1010" id="namedview4" showgrid="false" inkscape:zoom="0.56057661" inkscape:cx="524.20669" inkscape:cy="409.12716" inkscape:window-x="0" inkscape:window-y="33" inkscape:window-maximized="1" inkscape:current-layer="g10" />
<g id="g10" inkscape:groupmode="layer" inkscape:label="editable_Livebook_Logo" transform="matrix(1.3333333,0,0,-1.3333333,-271.62159,986.33208)">
<g id="g14">
<g id="g16" clip-path="url(#clipPath20)">
<g id="g118" transform="translate(425.3255,680.1453)">
<path d="M 0,0 C 27.577,33.093 44.051,35.111 44.303,34.988 53.563,33.872 54.75,25.563 54.75,25.563 L 48.815,7.759 36.397,-25.372 c -12.991,2.166 -50.193,4.688 -52.949,3.31 z" style="fill:#825161;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path120" />
</g>
<g id="g122" transform="translate(465.032,662.4954)">
<path d="m 0,0 c 0,0 1.103,3.31 3.309,9.928 0.149,0.446 -33.093,5.515 -55.154,-5.515 0,0 33.092,2.206 51.845,-4.413" style="fill:#563642;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path124" />
</g>
<g id="g126" transform="translate(416.4956,669.1141)">
<path d="m 0,0 5.638,59.34 c -1.225,10.155 -7.844,14.568 -18.421,8.598 -1.514,-0.854 -3.384,-2.171 -4.941,-3.407 -37.828,-30.007 -44.168,-81.382 -45.215,-106.367 0.017,-0.925 -0.012,-5.787 -0.051,-6.7 -0.989,-51.846 68.077,-90.357 87.258,-109.207 -3.976,7.409 -33.71,32.402 -37.505,50.743 -2.915,14.088 0.033,25.5 4.619,34.123 5.83,10.959 15.579,19.332 27.085,23.993 29.794,12.071 59.031,10.045 84.121,5.863 38.691,-6.448 69.005,-22.321 70.537,-23.132 0.041,-0.022 0.061,-0.033 0.061,-0.033 -0.028,0.014 1.707,6.516 0,9.928 -2.206,4.413 -7.109,6.373 -7.868,6.778 C 153.087,-42.987 98.646,-13.885 51.183,-3.768 54.052,-4.412 25.371,2.207 0,0" style="fill:#825161;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path128" />
</g>
<g id="g130" transform="translate(525.7024,616.1653)">
<path d="m 0,0 c -25.09,4.182 -50.834,4.135 -80.628,-7.936 -11.505,-4.661 -21.747,-14.412 -27.577,-25.371 -4.587,-8.622 -6.517,-17.435 -3.208,-33.982 2.632,-13.159 8.825,-26.474 14.341,-35.299 22.621,-18.788 30.59,-16.362 56.257,-31.99 -7.706,37.317 0.852,89.735 89.315,110.745 0.087,0.021 7.234,1.567 7.516,1.687 3.934,1.668 6.669,5.099 7.922,8.931 C 63.067,-12.751 39.14,-6.523 0,0" style="fill:#c4adb5;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path132" />
</g>
<g id="g134" transform="translate(589.6821,607.3406)">
<path d="m 0,0 c -13.237,4.413 -31.99,9.928 -57.708,16.292 -29.298,7.249 -64.537,10.376 -90.107,0.254 0,0 -58.464,-16.546 -38.609,-77.216 l 3.31,-13.237 c 0,0 6.581,0.003 13.812,-5.112 -1.147,3.495 -5.422,17.002 -6.132,20.567 -3.298,16.556 0.033,25.515 4.604,34.142 5.81,10.966 15.527,19.344 26.994,24.008 6.942,2.824 13.999,4.993 21.056,6.608 4.301,0.984 8.665,1.64 13.064,1.989 21.894,1.741 50.539,1.716 107.51,-12.707 l 0.154,0.464 c 0.948,-0.273 1.421,-0.421 1.421,-0.421 C -0.589,-4.391 0.177,-0.059 0,0" style="fill:#4c313b;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path136" />
</g>
<g id="g138" transform="translate(354.1892,303.2845)">
<path d="m 0,0 c -0.044,-10.08 2.465,-20.009 7.354,-28.825 9.226,-16.633 29.838,-42.629 75.711,-72.288 52.438,-33.904 146.912,-63.851 146.912,-63.851 l 13.238,291.422 c 0,0 -243.836,115.46 -243.836,197.646 C -0.621,326.15 0.245,55.466 0,0" style="fill:#dbd8d5;fill-opacity:1;fill-rule:evenodd;stroke:none" id="path140" />
</g>
<g id="g142">
<g id="g144" />
<g id="g156">
<g clip-path="url(#clipPath148)" opacity="0.25" id="g154">
<g transform="translate(359.1348,529.0208)" id="g152">
<path d="m 0,0 214.001,-88.248 v 1.103 L -5.516,15.443 V 2.206 c 0,0 0.102,-0.038 5.516,-2.206" style="fill:#36272b;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path150" />
</g>
</g>
</g>
</g>
<g id="g158" transform="translate(293.3445,165.7054)">
<path d="m 0,0 c -3.146,1.255 -5.206,4.305 -5.196,7.692 l 0.424,376.462 c -0.11,2.985 0.066,7.804 5.48,5.636 L 262.142,286.099 c 0,-3.309 0.015,-2.127 0,-5.516 l -0.648,-371.921 c -0.021,-4.584 0.648,-7.544 0.648,-10.854 C 262.142,-102.82 0,0 0,0" style="fill:#c24063;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path160" />
</g>
<g id="g162" transform="translate(555.4861,63.5135)">
<path d="m 0,0 260.943,102.192 c 3.146,1.255 5.206,4.305 5.196,7.692 l -0.424,376.462 c 0.061,1.642 -0.271,3.506 -1.483,4.489 -0.99,0.804 -2.569,1.019 -5.004,0.043 L 0,388.291 c 0,-4.413 -0.015,-2.127 0,-5.516 L -0.551,10.854 C -0.525,5.032 0,3.31 0,0" style="fill:#ff87a7;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path164" />
</g>
<g id="g166">
<g id="g168" />
<g id="g180">
<g clip-path="url(#clipPath172)" opacity="0.25" id="g178">
<g transform="translate(396.6399,125.2874)" id="g176">
<path d="m 0,0 c 0,0 25.629,-13.707 41.918,20.958 16.816,35.79 11.031,138.991 -39.073,206.638 0,0 33.557,-168.029 -47.585,-209.748 z" style="fill:#36272b;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path174" />
</g>
</g>
</g>
</g>
<g id="g182" transform="translate(235.1873,329.8465)">
<path d="m 0,0 -6.929,-91.382 c -1.889,-24.9 6.023,-49.032 22.274,-67.955 16.147,-18.923 39.281,-30.415 63.952,-32.286 5.208,-0.395 10.484,-0.359 15.781,0.124 44.579,4.068 80.894,42.703 84.471,89.866 l 3.337,44.017 C 187.631,4.953 156.231,63.07 102.889,90.441 59.026,112.964 14.225,107.04 -30.368,72.879 -9.406,54.897 2.1,27.688 0,0" style="fill:#1f2728;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path184" />
</g>
<g id="g186" transform="translate(311.2022,170.5091)">
<path d="m 0,0 c -16.25,18.924 -24.162,43.056 -22.274,67.956 l 6.93,91.381 c 2.099,27.689 -9.406,54.898 -30.368,72.879 16.567,12.692 33.162,21.478 49.728,26.364 -36.867,10.985 -74.257,2.169 -111.502,-26.364 20.962,-17.981 32.468,-45.19 30.368,-72.879 l -6.929,-91.381 c -1.889,-24.9 6.023,-49.032 22.274,-67.956 16.147,-18.922 39.281,-30.415 63.952,-32.286 5.208,-0.395 10.484,-0.359 15.781,0.125 7.571,0.691 14.895,2.4 21.87,4.958 C 24.539,-21.832 10.724,-12.567 0,0" style="fill:#2f393d;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path188" />
</g>
</g>
</g>
</g>
</svg>
#!/usr/bin/env elixir
Mix.install([
{:jason, "~> 1.4"}
])
{container_info, 0} = System.cmd("docker", ["inspect", "livebook"])
[%{"HostConfig" => %{"PortBindings" => %{"8080/tcp" => [%{"HostPort" => port}]}}}] =
Jason.decode!(container_info)
suffix =
case System.argv() do
["livebook://" <> _ = url] ->
url = %URI{URI.parse(url) | scheme: "https"} |> URI.to_string()
"/import?#{%{url: url} |> URI.encode_query()}"
_ ->
""
end
{_, 0} = System.cmd("xdg-open", ["http://localhost:#{port}#{suffix}"])
#!/usr/bin/env bash
iframe_port="$(elixir -e '
{:ok, socket} = :socket.open(:inet, :stream)
:ok = :socket.bind(socket, %{family: :inet, port: 0, addr: :loopback})
{:ok, %{port: iframe_port}} = :socket.sockname(socket)
:ok = :socket.close(socket)
IO.write(iframe_port)
')"
exec docker run \
--init \
--rm \
--name livebook \
--replace \
--hostname livebook \
-e LIVEBOOK_TOKEN_ENABLED=false \
-e LIVEBOOK_IFRAME_PORT=${iframe_port} \
-v livebook-data:/data \
-v livebook-config:/home/livebook/.local/share/livebook \
-p 127.0.0.1::8080 \
-p 127.0.0.1:${iframe_port}:${iframe_port} \
--pull newer \
ghcr.io/livebook-dev/livebook
[Unit]
Description=Livebook
[Service]
ExecStart=/path/to/livebook-daemon
[Install]
WantedBy=default.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment