使用Ankiweb同步卡片在我这里确实是有些慢,所以我自己尝试搭建了自己的Anki同步服务Ankisyncd,搭建好后又发现安卓版的Ankidroid只支持https同步,所以我又用Apache2对同步地址进行了反向代理。
文章前半部分其实还是老生常谈,最精华的,我觉得是反向代理那部分内容。这篇文章全文无图片,只有文字,可以看作是整个实现过程的思路和要点整理,我省去了很多前置步骤,例如许多命令我都是直接拿来用的,而它们在你自己的服务器中可能需要提前安装。 在文章最后会附上我所参考的资料,那里一般有完整、详细的说明,如果想自己搭建类似服务,遇到问题后建议先去浏览这些内容。 文章分成三部分,先介绍在服务器端怎样搭建Ankisyncd,之后介绍电脑版Anki和安卓版Ankidroid怎样配置,在Ankidroid同步失败后又介绍了在服务器端怎样用Apache2实现反向代理。我的服务器是阿里云的学生轻量应用服务器,系统版本是Ubuntu18.04。
服务器端
在服务器安装Ankisyncd[1]
大致过程如下[2]:
git clone https://github.com/tsudoko/anki-sync-server.git /usr/local/anki-sync-server
git submodule update --init
cd anki-bundled
pip3 install -r requirements.txt
# 可预先从requirements.txt中删去“pyaudio”,这个不是必装的。
pip3 install webob
修改/usr/local/anki-sync-server下的ankisyncctl.py文件,把开头的#!/usr/bin/env python
改为#!/usr/bin/env python3
按教程,这样就算安装好了,但我第二步但那条命令git submodule update --init
运行之后一直卡在Cloning into '/usr/local/anki-sync-server/anki-bundled'...
这里,原因是github访问速度太慢。我一开始想的办法是把github的仓库文件克隆到gitee(码云),修改 /usr/local/anki-sync-server下的.gitmodules
文件,把url改成码云的链接。我也在git里add和commit了,但还是卡在这里。后来我用了一个粗暴的办法,从github下载库文件后,直接上传到vps上,解压缩到anki-bundled文件夹里面。
安装完成。
启动Ankisyncd[3]
cd /usr/local/anki-sync-server
screen -S anki
python3 -m ankisyncd
之后在浏览器里访问“http://你的ip:27701”,浏览器页面上会显示一句“Anki Sync Server”。注意,如果访问不了,可能是需要在阿里云后台开放端口27701。
按Ctrl+A,D
,退出会话,Ankisyncd会继续在后台运行。
管理用户
创建用户:
cd /usr/local/anki-sync-server
./ankisyncctl.py adduser
回车后会提示输入密码。 其他操作:
Commands:
adduser - add a new user
deluser - delete a user
lsuser - list users
passwd - change password of a user
电脑端Anki配置
从Releases · tsudoko/anki-sync-server · GitHub了解到,Ankisyncd最新版本是2.1.0,支持的Anki版本是:Anki from 2.0.27 to 2.1.16;AnkiDroid 2.3 and up。也就是说,目前最新的Anki版本(2.1.38,2021年1月23日)是无法使用的。经测试,在2.1.38版本中用刚刚设定的账号和密码登录时会提示“用户名或密码错误”。我用的版本是2.1.15。从2.1.20开始就不正常、无法登录了(2.1.20还是2.1.21我给忘了,可以登录但同步有问题)。
Anki电脑版若要登录到自建服务器,需要安装一个插件。
打开“工具”——“附加组件”——“查看文件”,新建一个文件夹“AnkiServer”(随便命名),在新建的文件夹内新建文件__init__.py
,填入如下内容:
import anki.sync, anki.hooks, aqt
addr = "http://127.0.0.1:27701/" # put your server address here
anki.sync.SYNC_BASE = "%s" + addr
def resetHostNum():
aqt.mw.pm.profile['hostNum'] = None
anki.hooks.addHook("profileLoaded", resetHostNum)
把里面的ip地址换成你自己的服务器的地址。 重启Anki,点击同步按钮,输入用户名和密码即可正常同步。
安卓端Ankidroid配置
把上面的同步地址填入较新版本的Ankidroid(版本2.14.2),点击同步按钮会提示同步出错,因为那个地址是http的,而这种传输方式已被禁止。使用较低版本的Ankidroid(2.8.3),正常。 我不想使用旧版本的App,因此就需要让同步数据加密传输,即让同步地址由http变成https的。由于我的vps已经安装了Apache2,因此我使用Apache反向代理转发同步地址。 由于我对这块内容并不是很熟,所以下面的步骤当中肯定有冗余。 我的计划是,先配置一个不使用ssl的反向代理(使用80端口),然后用Certbot获取Let’s Encrypt证书(会自动生产一个新的conf配置文件,使用443端口)。
启用模块
a2enmod proxy
a2enmod proxy_http
a2enmod ssl
新建Apache配置文件
cd /etc/apache2/sites-available
vim your_domain.conf
在your_domain.conf文件中填入以下内容[4]
ServerName anki.xiake.me
ProxyPass http://127.0.0.1:27701/
ProxyPassReverse http://127.0.0.1:27701/
UseCanonicalName off
ProxyRequests off
ProxyPreserveHost on
保存后,启用配置
a2ensite your_domain-le-ssl.conf
systemctl reload apache2
在浏览器地址中填入你设置的域名,应该就能得到刚才访问那个ip地址一样的结果。
使用Certbot获得Let’s Encrypt的SSL证书[5]
certbot --apache -d your_domain
按提示操作即可,之后会得到一个新的conf配置文件,类似下面这样
ServerName your\_domain
ProxyPass http://127.0.0.1:27701/
ProxyPassReverse http://127.0.0.1:27701/
UseCanonicalName off
ProxyRequests off
ProxyPreserveHost on
SSLCertificateFile /etc/letsencrypt/live/your\_domain/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/your\_domain/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
重新加载配置,之后在浏览器里就可以使用加密地址访问了。
a2ensite your_domain-le-ssl.conf
systemctl reload apache2
在Ankidroid中的设置
打开“侧边栏”——“设置”——“高级设置”——“自定义同步服务器”,选中“使用自定义同步服务器”,把“同步地址”和“媒体文件同步地址”分别设为:
https://your_domain/
https://your_domain/msync
而后返回主页,点击同步按钮,输入设定的用户名和密码,就可以同步了。
参考资料
[1] github仓库, ankisyncd
[2] 知乎专栏文章, (一 超详细自架 Ankisyncd 版)
[3] 博客文章, Anki同步服务器搭建教程
[4] Anki Community Wiki, HTTPS Encryption with Apache Proxy
[5] How To Secure Apache with Let’s Encrypt on Ubuntu 18.04