YYiki is a personal wiki created and managed by yy.

The wiki engine is written in Python by yy. It uses Flat files (implemented with Flask + Flask-FlatPages) and Git to manage the pages. It uses Tufte CSS.

The source code is on GitHub.

Interface (behaviors)

Transitive actions


If the page at PAGEPATH exists, it renders the wiki page stored in the PAGEPATH. The PAGEPATH may contain subdirectories.

If the page does not exist, it redirects to /search/PAGEPATH


If the page exists, it shows the editing form pre-filled with the page stored in the PAGEPATH.

If it does not, it redirects to /create/PAGEPATH.


If the page exists, it redirects to /edit/PAGEPATH.

If it does not, it creates a new page (file) and then redirects to /edit/PAGEPATH.


If the exact match exists, it shows the link to it. Otherwise, show a hyperlink to /create/PAGEPATH.

At the same time, always show the fuzzy matches.

Intransitive actions


It shows the list of pages in reverse chronological order.


Server setup

Basic setup

Run the following commands.

apt update && apt upgrade
hostnamectl set-hostname yyiki
adduser xxxx
adduser xxxx sudo

Add the IP and the hostname in /etc/hosts below localhost.

Basic security

Copy the ssh public key to user’s .ssh/authorized_keys and test whether you can login.

Then edit the /etc/ssh/sshd_config file to change PermitRootLogin and PasswordAuthentication to no then run

sudo systemctl restart sshd
sudo apt install ufw
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow 5000
sudo ufw enable
sudo ufw status
sudo apt install python3-pip
sudo apt install python3-venv
python3 -m venv venv

to restart sshd and install & setup ufw (uncomplicated firewall).

App setup

Generate and add the SSH public key to GitHub and clone the yyiki and pages repos. Then install necessary python pacakges and create a virtual environment.

sudo apt install python3-venv
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp default_settings_template.py default_settings.py
python -c 'import os; print(os.urandom(16))'

Copy the default_settings_template.py to default_settings.py, and then put the generated secret key into the default_settings.py. Now we can test the app.

export FLASK_APP=yyiki.py
flask run --host=

Serving with a production webserver

We use Nginx and Gunicorn.

sudo apt install Nginx
pip install gunicorn
sudo cp /etc/nginx/sites-enabled/default /etc/nginx/sites-enabled/yyiki
sudo vi /etc/nginx/sites-enabled/yyiki
sudo ufw allow http/tcp
sudo ufw enable

The file would look like

server {
    listen 80;
    server_name yyiki.org;

    location /static {
            alias /home/yy/yyiki/static;

    location / {
            proxy_pass http://localhost:8000;
            include /etc/nginx/proxy_params;
            proxy_redirect off;

Then restart the nginx.

sudo systemctl restart Nginx
gunicorn -w 3 yyiki:app

And check whether it works.

sudo apt install supervisor
sudo vi /etc/supervisor/conf.d/yyiki.conf

The content will be

command=/home/yy/yyiki/venv/bin/gunicorn -w 3 


sudo mkdir -p /var/log/yyiki/
sudo touch /var/log/yyiki/yyiki.err.log
sudo touch /var/log/yyiki/yyiki.out.log
sudo supervisorctl reload

TLS with certbot

Install certbot.

sudo apt-get install python3-certbot-nginx
sudo certbot --nginx

Check this article too: linode: Installing Certbot for TLS on Ubuntu 18.04