Anki sync server: Difference between revisions

From stacky wiki
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 19: Line 19:
  vim production.ini  # set host to anki.stacky.net and set port
  vim production.ini  # set host to anki.stacky.net and set port
  ~/AnkiServer.env/bin/ankiserverctl.py adduser [USERNAME]
  ~/AnkiServer.env/bin/ankiserverctl.py adduser [USERNAME]
Disallow general access to anki server files (is there a better way to do this?):
chmod o-r -R collections/ production.ini session.db auth.db
Start the server:
  /AnkiServer.env/bin/ankiserverctl.py [start|stop|debug]
  /AnkiServer.env/bin/ankiserverctl.py [start|stop|debug]


Line 128: Line 133:
  source ~/.bashrc
  source ~/.bashrc


Create <code>~Documents/Anki/addons/mysyncserver.py</code> with contents
Create <code>~/.local/share/Anki2/addons/mysyncserver.py</code> (previously <code>~/Documents/Anki/addons/mysyncserver.py</code>) with contents
  import anki.sync
  import anki.sync
  anki.sync.SYNC_BASE = 'http://anki.stacky.net:PORT/'
  anki.sync.SYNC_BASE = 'http://anki.stacky.net:PORT/'
Line 134: Line 139:


where PORT is port from production.ini on the server.
where PORT is port from production.ini on the server.
= debugging =
== Exception: Anki requires a UTF-8 locale.==
Anki sync server is failing to start. Running it in debug mode gives the exception
Exception: Anki requires a UTF-8 locale.
which coming from the fact that <code>sys.getfilesystemencoding()</code> is 'ANSI_X3.4-1968'. This seems to have something to do with locales (i.e. is a problem with dreamhost rather than anki sync server). Current output of <code>locale</code>:
$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE=C
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=
Just doing <code>export LC_CTYPE=en_US.UTF-8</code> seems to fix the problem, but probably isn't the right way to do it. I have
$ locale -a | grep en_US
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8
but doing <code>locale en_US.utf8</code> says "unknown name en_US.utf8". Same for "en_US.UTF-8", even though there's a line for that in /usr/share/i18n/SUPPORTED.
I can generate locale files with
localedef -f UTF-8 -i en_US ~/en_US.UTF-8
but how do I ask to use them?
Oh well. Adding the following to bashrc:
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8

Latest revision as of 06:15, 20 September 2018

On dreamhost

Add hosting for domain anki.stacky.net pointing to /home/username/anki.stacky.net.

virtualenv AnkiServer.env
. AnkiServer.env/bin/activate
easy_install AnkiServer

Apply patches to avoid "inconsistent database" error. See [1]; patches copied below.

cd ~/AnkiServer.env/lib/python2.7/site-packages/AnkiServer-2.0.6-py2.7.egg/
patch -p0 < ~/AnkiServer.env/anki-sync-server.patch.txt
cd ~/AnkiServer.env/lib/python2.7/site-packages/AnkiServer-2.0.6-py2.7.egg/anki-bundled/
patch -p0 < ~/AnkiServer.env/anki.patch.txt

Set up:

cd ~/anki.stacky.net/
cp ../AnkiServer.env/examples/example.ini production.ini
vim production.ini  # set host to anki.stacky.net and set port
~/AnkiServer.env/bin/ankiserverctl.py adduser [USERNAME]

Disallow general access to anki server files (is there a better way to do this?):

chmod o-r -R collections/ production.ini session.db auth.db

Start the server:

/AnkiServer.env/bin/ankiserverctl.py [start|stop|debug]

Debug is useful to see requests coming in. Start and stop run in daemon mode.

(patches)

anki.patch.txt:

diff -urN anki/collection.py anki/collection.py
--- anki/collection.py	2016-10-22 00:04:43.365953912 +0200
+++ anki/collection.py	2016-10-23 10:46:26.171300370 +0200
@@ -60,7 +60,7 @@
         self.server = server
         self._lastSave = time.time()
         self.clearUndo()
-        self.media = MediaManager(self, server)
+        self.media = MediaManager(self)
         self.models = ModelManager(self)
         self.decks = DeckManager(self)
         self.tags = TagManager(self)
diff -urN anki/media.py anki/media.py
--- anki/media.py	2016-10-22 00:04:43.367953863 +0200
+++ anki/media.py	2016-10-23 10:46:16.947524341 +0200
@@ -26,11 +26,8 @@
     ]
     regexps = soundRegexps + imgRegexps
 
-    def __init__(self, col, server):
+    def __init__(self, col):
         self.col = col
-        if server:
-            self._dir = None
-            return
         # media directory
         self._dir = re.sub("(?i)\.(anki2)$", ".media", self.col.path)
         # convert dir to unicode if it's not already
@@ -51,8 +48,6 @@
         self.connect()
 
     def connect(self):
-        if self.col.server:
-            return
         path = self.dir()+".db2"
         create = not os.path.exists(path)
         os.chdir(self._dir)
@@ -103,8 +98,6 @@
             os.rename("../collection.media.db", npath)
 
     def close(self):
-        if self.col.server:
-            return
         self.db.close()
         self.db = None
         # change cwd back to old location

anki-sync-server.patch.txt:

diff -urN AnkiServer/apps/sync_app.py AnkiServer/apps/sync_app.py
--- AnkiServer/apps/sync_app.py	2016-10-21 22:14:27.672485051 +0200
+++ AnkiServer/apps/sync_app.py	2016-10-26 23:18:24.287625612 +0200
@@ -471,6 +471,7 @@
             os.rename(temp_db_path, session.get_collection_path())
         finally:
             col.reopen()
+            col.load()
 
         # If everything went fine, run hook_upload if one is defined.
         if self.hook_upload is not None:
@@ -488,6 +489,7 @@
             data = open(session.get_collection_path(), 'rb').read()
         finally:
             col.reopen()
+            col.load()
         return data
 
     @wsgify
diff -urN AnkiServer/collection.py AnkiServer/collection.py
--- AnkiServer/collection.py	2016-10-21 22:14:27.672485051 +0200
+++ AnkiServer/collection.py	2016-10-23 10:38:47.869428818 +0200
@@ -75,7 +75,7 @@
             else:
                 raise
 
-        col = anki.storage.Collection(self.path)
+        col = anki.storage.Collection(self.path, server=True)
 
         # Do any special setup
         if self.setup_new_collection is not None:
@@ -87,7 +87,7 @@
         """Open the collection, or create it if it doesn't exist."""
         if self.__col is None:
             if os.path.exists(self.path):
-                self.__col = anki.storage.Collection(self.path)
+                self.__col = anki.storage.Collection(self.path, server=True)
             else:
                 self.__col = self.__create_collection()

On Ankidroid

Under Settings > Advanced > Custom sync server, Set sync url to http://anki.stacky.net:[port] and media sync url to http://anki.stacky.net:[port]/msync

Under Settings > AnkiDroid, set AnkiWeb account to username and password set on the server.

On Anki desktop

Make sure python can do import anki with

sudo easy_install AnkiServer
echo export PYTHONPATH=\"\${PYTHONPATH}:/usr/local/lib/python3.5/dist-packages/AnkiServer-2.0.6-py3.5.egg/anki-bundled/\" >> ~/.bashrc
source ~/.bashrc

Create ~/.local/share/Anki2/addons/mysyncserver.py (previously ~/Documents/Anki/addons/mysyncserver.py) with contents

import anki.sync
anki.sync.SYNC_BASE = 'http://anki.stacky.net:PORT/'
anki.sync.SYNC_MEDIA_BASE = 'http://anki.stacky.net:PORT/msync/'

where PORT is port from production.ini on the server.

debugging

Exception: Anki requires a UTF-8 locale.

Anki sync server is failing to start. Running it in debug mode gives the exception

Exception: Anki requires a UTF-8 locale.

which coming from the fact that sys.getfilesystemencoding() is 'ANSI_X3.4-1968'. This seems to have something to do with locales (i.e. is a problem with dreamhost rather than anki sync server). Current output of locale:

$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE=C
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

Just doing export LC_CTYPE=en_US.UTF-8 seems to fix the problem, but probably isn't the right way to do it. I have

$ locale -a | grep en_US
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8

but doing locale en_US.utf8 says "unknown name en_US.utf8". Same for "en_US.UTF-8", even though there's a line for that in /usr/share/i18n/SUPPORTED.

I can generate locale files with

localedef -f UTF-8 -i en_US ~/en_US.UTF-8

but how do I ask to use them?

Oh well. Adding the following to bashrc:

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8