#+title: Setup #+property: header-args :comments no #+property: header-args:sh :tangle yes :shebang "#!/usr/bin/env sh" :eval no We could do something fancy like a NixOS flake, but for the [[https://git.tecosaur.net/tec/emacs-survey][Emacs Survey]] server I think a simple Debian machine with a setup script should do the trick. Let's just work out a setup script to get everything up and running. The idea is that this repository can be cloned/updated anywhere on the machine and =sudo setup.sh= will do the rest. In fact, here's a snippet to do exactly that: #+begin_src sh :tangle no git clone https://git.tecosaur.net/tec/emacs-survey-server.git /tmp/emacs-survey-server /tmp/emacs-survey-server/setup.sh #+end_src Remember to (re)start services as appropriately, as this script leaves that to be done manually. * Installing software ** Caddy web server #+begin_src sh if ! dpkg -s caddy > /dev/null; then printf "\e[1;34mInstalling Caddy\e[m\n" # Taken from sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy fi #+end_src There are two notable extras that come with the Caddy software itself here: 1. A systemd service automatically started that loads =/etc/caddy/Caddyfile=. 2. The =caddy= user and =caddy= group. ** Julia First, we specify the Julia version we want and hope that the relevant paths continue to be predictable. #+begin_src sh JULIA_VERSION="1.8.2" #+end_src If either the =julia= command does not exist, or =julia --version= does not match the expected output, then we will install Julia in =/opt/julia= and symlink the binary into =/usr/bin=. #+begin_src sh if ! command -v julia > /dev/null || [ ! "$(julia --version)" = "julia version $JULIA_VERSION" ]; then printf "\e[1;34mInstalling Julia\e[m\n" cd /tmp || exit 2 # Following wget "https://julialang-s3.julialang.org/bin/linux/x64/${JULIA_VERSION%.*}/julia-$JULIA_VERSION-linux-x86_64.tar.gz" mkdir -p "/opt/julia/" tar zxf "julia-$JULIA_VERSION-linux-x86_64.tar.gz" --directory=/opt/julia ln -sf "/opt/julia/julia-$JULIA_VERSION/bin/julia" /usr/bin/julia fi #+end_src * Copying over relevant files Before starting to do this, we will obtain the path to the folder of the script, so we can grab files relative to the root of this repository. #+begin_src sh SETUPDIR=$(dirname "$(readlink --canonicalize-existing "$0")") #+end_src ** Caddy Config :PROPERTIES: :header-args:prog: :tangle Caddyfile :END: We just need to redirect to Genie for now, which makes for a rather simple config. The only complication is serving the static files through Caddy not Genie, for performance reasons (Genie recommends against serving static files with it). #+begin_src prog emacssurvey.tecosaur.net emacssurvey.org @dynamic { not path /css/* not path /faq.html not path /favicon.ico not path /robots.txt } reverse_proxy @dynamic localhost:8000 #+end_src We'll just pass all other requests to the public folder of the Emacs Survey. #+begin_src prog root * /opt/emacs-survey/public file_server #+end_src For HTTP errors we could re-use the Genie error pages ... or have some fun 🐱. #+begin_src prog handle_errors { rewrite * /{err.status_code} reverse_proxy https://http.cat { header_up Host {upstream_hostport} } } #+end_src Just this one file is all it takes to get Caddy set up to our liking 🙂. #+begin_src sh cp -f "$SETUPDIR/Caddyfile" "/etc/caddy/Caddyfile" #+end_src ** Emacs Survey Before we start copying files, we want to make sure these files are owned by the =genie= user, and so me must first ensure that the user exists. #+begin_src sh if ! id genie >/dev/null; then groupadd -f genie useradd -r -g genie -m -d /var/lib/genie genie fi #+end_src This is actually a separate repo, so we need to ensure it exists, and update it if it does. #+begin_src sh if [ -d /opt/emacs-survey ]; then cd /opt/emacs-survey || exit 2 printf "\e[1;34mUpdating emacs-survey\e[m\n" sudo -u genie git pull origin main --ff-only else mkdir -p /opt/emacs-survey chown genie:genie /opt/emacs-survey printf "\e[1;34mCloning emacs-survey\e[m\n" sudo -u genie git clone https://git.tecosaur.net/tec/emacs-survey /opt/emacs-survey fi #+end_src Then lets make sure that the packages are up to date. #+begin_src sh printf "\e[34mInstantiating emacs-survey\e[m\n" sudo -u genie julia --project=/opt/emacs-survey -e 'using Pkg; Pkg.instantiate()' #+end_src We also need to ensure that a secrets token exists. #+begin_src sh if [ ! -e "/opt/emacs-survey/config/secrets.jl" ]; then printf "\e[34mCreating genie secrets token\e[m\n" cd /opt/emacs-survey sudo -u genie julia --project=/opt/emacs-survey -e 'using Genie; Genie.Generator.write_secrets_file()' fi #+end_src * Genie service To actually run the survey, we'll use a systemd service. #+begin_src systemd :tangle genie-app.service [Unit] Description=Genie app After=network.target network-online.target Requires=network-online.target [Service] Type=simple Restart=on-failure User=genie Group=genie ExecStart=/opt/emacs-survey/bin/server WorkingDirectory=/opt/emacs-survey Environment="GENIE_ENV=prod" Environment="JULIA_NUM_THREADS=auto" [Install] WantedBy=multi-user.target #+end_src Then we need to put this is the systemd folder, and make sure it is aware of the latest version of the service. #+begin_src sh cp -f "$SETUPDIR/genie-app.service" /etc/systemd/system/ systemctl daemon-reload #+end_src To get this up and running, all one has to do is execute the following: #+begin_src sh :tangle no systemctl enable --now genie-app.service #+end_src