codomari · sync · rsync · remote

Codomari #2 (remote deployment)

As the part of development I wanted to synchronize my work to remote server and make it available to public.

There are many ways to achieve auto-deployment:

  1. GitHub Actions - configuring deploy step
  2. IDE plugins which run synchronization on save or manually by call
  3. Having script which we call manually to do rsync

I’m developing locally, after pushing to github my code, only after that if I decide that it’s good show public my latest work I do update remote application.

That’s why I’ve created simple rsync script which I call when I want to synchronize my remote code:

#!/bin/zsh

# Variables
LOCAL_DIR="/Users/num8er/My/Codomari/codomari_backend/"
REMOTE_USER="num8er"
REMOTE_HOST="srv0.codomari.com" # e.g., example.com or an IP address
REMOTE_DIR="/apps/codomari_backend"

# Rsync command
rsync -avz --delete \
    --exclude-from=".sync_backend.exclude" \
    "$LOCAL_DIR" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR"

# Explanation of options:
# -a: Archive mode (preserves permissions, timestamps, symbolic links, etc.)
# -v: Verbose output
# -z: Compress data during transfer
# --delete: Deletes files on the destination that are not in the source
# --exclude-from="exclusion list file": Exclude files and directories listed in the specified file

VERSION=$(grep -E 'version:' mix.exs | sed -E "s/.*version: \"([^\"]+)\".*/\1/")

ssh -t $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_DIR ; rm -rf deps && mix deps.get"
ssh -t $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_DIR ; MIX_ENV=dev mix release codomari_backend --overwrite --path _releases --version $VERSION"
ssh -t $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_DIR ; rm -rf _releases/$VERSION ; mkdir _releases/$VERSION ; cd _releases ; tar -zxf codomari_backend-$VERSION.tar.gz -C $VERSION"
ssh -t $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_DIR ; cd _releases/$VERSION ; ./bin/codomari_backend stop ; sleep 1 ; ./bin/codomari_backend daemon"

what it does?

  1. gets version of project from mix.exs and defines it to $VERSION
  2. creates release in _releases folder, release file is named as: $RELEASE_NAME-$VERSION , release name defined in mix.exs file mix.exs
  3. creates _releases/$VERSION folder on remote machine and extracts archive contents there
  4. stops running instance (if exists) and starts new version as daemon

as result in remote server we can see such structure:

┌[num8er☮codomari0]-(/apps/codomari_backend/_releases)
└> ls -al
total 18312
drwxr-xr-x  8 num8er num8er    4096 Nov 30 01:57 .
drwxr-xr-x 10 num8er num8er    4096 Nov 30 01:57 ..
drwxr-xr-x  7 num8er num8er    4096 Nov 30 01:54 0.0.1
drwxr-xr-x  7 num8er num8er    4096 Nov 30 01:57 0.0.2
drwxr-xr-x  2 num8er num8er    4096 Nov 30 01:31 bin
-rw-r--r--  1 num8er num8er 9356817 Nov 30 01:54 codomari_backend-0.0.1.tar.gz
-rw-r--r--  1 num8er num8er 9358146 Nov 30 01:57 codomari_backend-0.0.2.tar.gz
drwxr-xr-x  3 num8er num8er    4096 Nov 30 01:31 erts-13.1.5
drwxr-xr-x 50 num8er num8er    4096 Nov 30 01:57 lib
drwxr-xr-x  4 num8er num8er    4096 Nov 30 01:57 releases

┌[num8er☮codomari0]-(/apps/codomari_backend/_releases)
└> ls -la 0.0.2
total 28
drwxr-xr-x  7 num8er num8er 4096 Nov 30 01:57 .
drwxr-xr-x  8 num8er num8er 4096 Nov 30 01:57 ..
drwxr-xr-x  2 num8er num8er 4096 Nov 30 01:57 bin
drwxr-xr-x  3 num8er num8er 4096 Nov 30 01:57 erts-13.1.5
drwxr-xr-x 49 num8er num8er 4096 Nov 30 01:57 lib
drwxr-xr-x  3 num8er num8er 4096 Nov 30 01:57 releases
drwxr-xr-x  4 num8er num8er 4096 Nov 30 01:57 tmp

┌[num8er☮codomari0]-(/apps/codomari_backend/_releases)
└> ls -la bin
total 16
drwxr-xr-x 2 num8er num8er 4096 Nov 30 01:31 .
drwxr-xr-x 8 num8er num8er 4096 Nov 30 01:57 ..
-rwxr-xr-x 1 num8er num8er 5317 Nov 30 01:57 codomari_backend
┌[num8er☮codomari0]-(/apps/codomari_backend/_releases/0.0.2)
└> bin/codomari_backend version
codomari_backend 0.0.2

┌[num8er☮codomari0]-(/apps/codomari_backend/_releases/0.0.2)
└> bin/codomari_backend pid
52789

So this scripts make bundled archive puts all stuff to remote location, extracts files from archive to versioned folder and replaces running instance with new one.

Compilation and releasing of binary file happens on remote machine for better OS compatibility.

For now I’m not thinking about gracefully replace application.

Also not going to add this procedure to GitHub Actions when I’m releasing (tagging) commit version of app, since we are still at dev stage and need to concentrate on development.


Next post will be about making landing page and api route which will respond with api version.


Talk Soon!