Anki like note reminders

I use my simple note system to scribble down thoughts, project descriptions, reminders from meetings and the usual note kinda stuff.

Despite of its intrinsic value, most notes gets written down and never revisited. Here is a short snippet that, based on the note's dated titles, email me the note after 2, 7, 14 and 30 days. The repetitions are carefully chosen spaced intervals after the Anki method, optimized for making stuff easier to remember.

#!/bin/bash

notes_dir="$HOME/sync/notes/"
interval="2 7 14 30"

email="note-reminder@torvald.no"

for i in $interval; do
    date=$(date --date="$i days ago" +"%Y-%m-%d")
    while read -r file; do
        subject=$(echo "$i days since $file" | sed "s,$notes_dir,,")
        cat "$file" | mail -r "Note reminder <$email>" -s "$subject" "$email"
    done < <(find "$notes_dir" | grep "$date")
done

I simply have this snippet in my crontab.

screenshot An test email.

A hacker's replacement for Dropbox (and that old NAS in the basement with dying hard drives)

TL;DR My answer here is rclone (mount) + insert-favorite-cloud-storage (I use Jottacloud) + Seafile on top. Multiple levels of accessibility, no more Dropbox and worrying about hard drives. Scroll to the bottom for a best effort Draw.io diagram. (-:

Perhaps you can relate; I had a Dropbox account on a free tier, always 90% full — and I had images, videos and random stuff laying around on multiple laptops and servers, wherever stuff made sense in the moment. Everything in my Dropbox was encrypted with encfs, but except for that, the situation was not ideal.

I decided to make a change for the better when I bought myself a new mobile phone and found out that Dropbox had introduces a max limit on the number of connected devices. So short story long;

I needed to

  • buy or find something to replace Dropbox, meaning; have a folder on each personal computer and server that is
    • synced across devices,
    • actual files on the file systems and
    • encrypted at third party.
  • find some kind of archive system to dump archive graded stuff without making them inaccessible.
    • I really would like to not worry about physical hard drives.
    • Bonus if I can mount the archive as a local file system.

I was discussing Plex with a colleague, he had all of his media content encrypted in his Google Drive account, mounted – like sshfs – to his server with rclone! Interesting!

I am really not an advocate for Google's products, but rclone supports a range of backends and one of them happens to be Jottacloud! There is nothing unique with Jottacloud, but they are Norwegians and it feels good to support Norwegian cloud provides when I can! The $7.5 per month plan gives me «unlimited storage» 1, and with rclone I will have a layer of indirection in case I ever want to swap backend.

This fixed my archive problem, but did not work well as a Dropbox replacement. Editing files which are mounted (very) remotely can sometimes take multiple seconds to open and write. And every now and then I want to access my files while I am offline or on a low bandwidth connection.

/r/selfhosted suggested Seafile! I have used it briefly in the past, at a former workplace, but it looks a lot more mature now.

So my life now looks like this! ↓

diagram

In short; I now got two folders on every client (desktops and servers) I use where sync is an Seafile folder with offline content, and archive; being a slower, albeit unlimited, file system folder. With this I can edit and use my notes and daily files via the former, and run borg backup 2, image/video gallery etc in the latter.

torvald@gauda ~/sync $ ls
bin  certs  docs  dotfiles  gpg  scrape  mailattachments  notes  projects  tickets  work  www
torvald@gauda ~/jotta/archive $ ls
backups  gitrepos  lekvam_cam  pictures  videos  www

Run rclone config to add your preferred cloud storage resources. Add additional layers with encryption. I divided the two use cases, but one remote folder with two subfolders is also a possibility. 3

torvald@gauda ~ $ rclone listremotes --long
jotta-archive-encrypted: crypt
jotta-archive-raw:       jottacloud
jotta-sync-encrypted:    crypt
jotta-sync-raw:          jottacloud

Further, rclone allows us to mount external resources to your file system with rclone mount. Make it persistent with systemd.

[Unit]
Description=Mount jotta crypt archive
Wants=network.target
Before=network.target

[Service]
Type=forking
User=torvald
Group=torvald
WorkingDirectory=/home/torvald
ExecStart=/usr/bin/rclone mount --allow-other --daemon jotta-archive-encrypted: /home/torvald/jotta/archive

[Install]
WantedBy=multi-user.target

Seafile comes with a well written guides for both server setup as well as desktop and CLI clients. Seafile's data directory is simply pointed to my rclone mounted sync folder. The default SQLlite did not work well with this approach, so I set up a Seafile with MySQL. No PostgreSQL support is a bummer.

Bonus: The Seafile android app also allows for auto photo upload, archiving my photos to a «selfhosted» encrypted location automatically.


  1. They limit bandwidth when you exceed 5TB, but I guess I'm good for a couple of years as is. 

  2. A friend have already blogged about this 

  3. You can instead encrypt your content with Seafile if you want, but if you want to add unencrypted Seafile libraries as well (i.e for sharing) rclone encryption is a nice default anyhow. 

My dead simple note system

I'm a fan of the terminal and a thoughtfully chosen $EDITOR variable. But enough with the intro. Here is my system, in action. Around 100 lines of bash and a directory with sets of plain text files.

A new document

torvald@gauda ~ $ note
[0] /home/torvald/notes/private
[1] /home/torvald/notes/work
[2] /home/torvald/notes/woodworking

Choose: [0]: 
Title: bathroom inspiration 
# Opens vim - edit and exit
/home/torvald/notes/private/2019-10-10_bathroom_inspiration.txt
torvald@gauda ~ $

Search for documents

torvald@gauda ~ $ note bathroom
Title serach:
[0] notes/private/./2019-10-10_bathroom_inspiration.txt
Content serach:
[1] notes/private/2019-04-02_home_improvments.txt (..the old bathroom light mus..)
[2] notes/private/2019-03-11_ideas_from_trip.txt (..- A bathroom closet..)
--
Enter number [0]:

The script

#!/bin/bash

ROOT=/home/torvald/notes
CATEGORIES="private work woodworking"

for folder in $CATEGORIES; do
    mkdir -p "$ROOT/$folder"
done

function search() {

    search=$1
    hits=()

    ####################
    # Seach by file name
    ####################

    echo "Title serach:"

    i=0
    for folder in $CATEGORIES; do
        cd "$ROOT/$folder" || continue
        for line in $(find . -maxdepth 1 | grep \.txt$ | grep "$search"); do
            hits[$i]=$folder/$line
            echo "[$i] $folder/$line"
            i=$((i + 1))
        done
    done

    ##################
    # Seach by content
    ##################

    echo "Content serach:"

    for folder in $CATEGORIES; do
        cd "$ROOT/$folder" || continue
        # TODO make --name
        for line in $(ag --depth 0 --files-with-matches "$search" | grep \.txt$); do
            context=$(grep -E -o ".{0,10}$search.{0,10}" "$line" | head -n 1)
            hits[$i]=$folder/$line
            echo "[$i] $folder/$line (..$context..)"
            i=$((i + 1))
        done
    done

    #################
    # Choose document
    #################

    # Only one hit, auto open
    if [[ "$i" == "1" ]]; then
        echo "Only one hit, opening $ROOT/${hits[1]}"
        sleep 1
        $EDITOR "$ROOT/${hits[1]}"
        exit 0

    # No hits
    elif [[ "$i" == "0" ]]; then
        echo "No hits."
        exit 1
    fi

    # Multiple hits
    echo "--"
    echo -n "Enter number [0]: "

    read -r index
    if [[ $index == "" ]]; then
        index="0"
    fi
    echo "$ROOT/${hits[$index]}"

    $EDITOR "$ROOT/${hits[$index]}"

    exit 0
}

function new_note() {

    ############################
    # List and choose categories
    ############################

    i=0
    for folder in $CATEGORIES; do
        echo "[$i] $ROOT/$folder"
        i=$((i + 1))
    done

    echo ""
    echo -n "Choose: [0]: "

    read -r foldernumber

    if [[ $foldernumber == "" ]]; then
        foldernumber="1"
    fi

    choosen=$(echo "$CATEGORIES" | cut -d' ' -f$foldernumber)
    folder=$ROOT/$choosen

    if ! [ -d "$folder" ]; then
        echo "Folder $folder does not exists"
        exit 1
    fi

    #######################
    # Choose title and open
    #######################

    echo -n "Title: "
    read -r filename

    filename=$(echo "$filename" | sed 's/ /_/g' | tr '[:upper:]' '[:lower:]')

    DATE=$(date +%Y-%m-%d)

    $EDITOR "$folder"/"$DATE"_"$filename".txt

    echo "$folder"/"$DATE"_"$filename".txt
}

if [[ $1 != "" ]]; then
    search "$1"
else
    new_note
fi

Future thoughts

  • Maybe I'll add a small daemon that runs grip, to render Markdown through a simple http server (apt-get install grip).
  • Maybe I'll add an interface to this somehow for my phone, but I'm not no fan of mobile typing, so I guess not.
  • Maybe I'll add an option to move a file to my web server which in turn returns a public and random link for sharing.
  • Maybe you have ideas?

Norske og habile passfraser

xkcd

Du har sett denne; en lett blanding av tilfeldige ord kan være langt mer habilt enn korte og knotete passord. Men fire «tilfeldige» ord man selv skal finne på blir sjeldent veldig tilfeldig. Debian (med venner) har i pakkebrønnene sine hele ordlister fra de fleste språk. Under er litt bash for å hente ut tilfeldige ord for å generere norske og habile passfraser.

torvald@gauda ~ $ sudo apt-get install wnorwegian
torvald@gauda ~ $ egrep "^.{3,8}$" /usr/share/dict/bokmaal | wc -l
112110
torvald@gauda ~ $ egrep "^.{3,8}$" /usr/share/dict/bokmaal | sort -R | tail -n 40 | sed 'N;N;N;s/\n/ /g' 
kannen luserne utkokene nesen
melker visperer pilkinga samtykt
rustende probert lykkes thaien
snakksom forkava troika liker
fremlagt syringer staplene doen
klebre spisse lyter leik
snaue brekke driller totiden
sletta snesene utebase huniske
heks gjentok fangsten vassing
madrass murverka danske duskende