加密文档分享|Cryptpad的自搭建教程

Privacy Protection系列

隐私高于一切

1.写在前面

你有没有这样一种需求?

一天,你想要分享一个文档给你的朋友。你不希望这个文档被其他人看到,或者看了一次之后就马上销毁。

有什么可选择的方法呢?

PrivateBin?这个可以,但是它不支持带点图片的文本。虽说markdown支持base64形式的图片,但如果图片很多呢?

nextcloud?这个也行,但是我之前连接onlyoffice时总是会断连,体验不怎么好。

又或者,你想对外分享一个文档,但是只能看,不允许下载或者编辑什么的,并且再来个定时销毁。

那么,Cryptpad无疑是一个好的选择。

但是,目前为止(2025/3/25),网上关于如何搭建cryptpad的中文教程寥寥无几,且官方教程没有中文版本。

所以我这里基于官方文档简单的讲一下搭建过程,非docker搭建。

2.准备工作

根据官方的文档,你需要至少这个配置的服务器:

  • Debian 12
  • 2GB RAM
  • 2 CPUs
  • 20GB storage (depending on planned usage)

另外,最好准备两个域名,两个子域名也可以,比如:

aaa.test.com

bbb.test.com

这两个都是可以的。

还有准备git和node.js这两个东西。

对于node.js,先执行这个命令。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash

这会安装nvm。

然后。

nvm list-remote

如果bash告诉你没有vm这个命令,就输入bash然后回车刷新一下环境变量。

你应该会看到如下输出:

...
        v22.0.0
        v22.1.0
        v22.2.0
        v22.3.0
        v22.4.0
        v22.4.1
        v22.5.0
        v22.5.1
        v22.6.0
        v22.7.0
        v22.8.0
        v22.9.0
       v22.10.0
       v22.11.0   (LTS: Jod)
       v22.12.0   (LTS: Jod)
       v22.13.0   (LTS: Jod)
       v22.13.1   (LTS: Jod)
       v22.14.0   (Latest LTS: Jod)
        v23.0.0
        v23.1.0
        v23.2.0
        v23.3.0
        v23.4.0
        v23.5.0
        v23.6.0
        v23.6.1
        v23.7.0
        v23.8.0
        v23.9.0
       v23.10.0

这是让你选择一个版本,编写本文时,最新的LTS是22.14.0(代号Jod),所以我们安装这个。

nvm install lts/Jod

如果安装成功,那么:

root@debian:/etc/bind# node -v
v22.14.0

安装bower:

npm install -g bower

按照官方教程,克隆cryptpad的github库。

git clone https://github.com/cryptpad/cryptpad.git cryptpad

然后设置一下权限

chmod 755 ./cryptpad -R
chown www-data:www-data ./cryptpad -R

然后cd进入文件夹,开始配置。

3.配置

搞一下依赖:

npm ci
npm run install:components

用官方的安装脚本安装onlyoffice:

./install-onlyoffice.sh

然后会显示一个用户协议,按Q退出,然后Y回车。

好了之后,开始改配置文件,先复制一份模板。

cp config/config.example.js config/config.js

主要就改两个地方,httpUnsafeOrigin和httpSafeOrigin。

httpUnsafeOrigin改成你的主域名,httpsafeOrigin改成沙盒域名,httpSafeOrigin前面有注释,要取消。

事实上,虽然不配置httpSafeOrigin也可以用,但是上次我在docker运行时如果不配置httpSafeOrigin,那么有些UI的功能会用不了,比如点击按钮没反应。

配置完成后,可以在cryptpad的目录下用node server命令启动服务。它会返回一个安装配置URL,但是我不推荐这么启动,所以我们把它给systemd。

nano ~/cryptpad/docs/cryptpad.service

下面是我改好的配置文件:

# SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <[email protected]> and contributors
#
# SPDX-License-Identifier: AGPL-3.0-or-later

[Unit]
Description=CryptPad API server

[Service]
ExecStart=/root/.nvm/versions/node/v22.14.0/bin/node /root/cryptpad/server.js
# modify to match the location of your cryptpad repository
WorkingDirectory=/root/cryptpad

Restart=always
# Restart service after 10 seconds if node service crashes
RestartSec=2

# Proper logging to journald
StandardOutput=journal
StandardError=journal+console

User=root
Group=root
# modify to match your working directory
Environment='PWD="/root/cryptpad"'

# systemd sets the open file limit to 4000 unless you override it
# cryptpad stores its data with the filesystem, so you should increase this to match the value of `ulimit -n`
# or risk EMFILE errors.
LimitNOFILE=1000000

# hardening directives as per https://www.freedesktop.org/software/systemd/man/systemd.exec.html
# check those with systemd-analyze security cryptpad.service for more information
# Proc filesystem
ProcSubset=all
ProtectProc=invisible
# Capabilities
CapabilityBoundingSet=
# Security
NoNewPrivileges=true
# Sandboxing
ProtectSystem=strict
PrivateTmp=true
PrivateDevices=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_INET
RestrictAddressFamilies=AF_INET6
RestrictAddressFamilies=AF_NETLINK
RestrictAddressFamilies=AF_UNIX
RestrictNamespaces=true
LockPersonality=true
RestrictRealtime=true
RestrictSUIDSGID=true
RemoveIPC=true
PrivateMounts=true
ProtectClock=true
# System Call Filtering
SystemCallArchitectures=native
SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid
SystemCallFilter=@chown
SystemCallFilter=pipe
SystemCallFilter=pipe2
ReadWritePaths=/root/cryptpad

[Install]
WantedBy=multi-user.target

对于模板的配置文件,你需要配置node可执行文件的路径。事实上,它在用户家目录里,就比如root,它在/root/.nvm/versions/node/v22.14.0/bin/node

然后就是你把cryptpad克隆到的目录,如果你也是用root,并且git clone在家目录,那么我的这个配置文件你可以直接复制粘贴用了。

改好之后,cp过去给systemd

cp ~/cryptpad/docs/cryptpad.service /etc/systemd/system/cryptpad.service
sudo systemctl daemon-reload

然后启动并查看状态。

systemctl enable cryptpad --now
systemctl status cryptpad
root@debian:~/cryptpad# systemctl enable cryptpad --now
Created symlink /etc/systemd/system/multi-user.target.wants/cryptpad.service -> /etc/systemd/system/cryptpad.service.
root@debian:~/cryptpad# systemctl status cryptpad
* cryptpad.service - CryptPad API server
     Loaded: loaded (/etc/systemd/system/cryptpad.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-03-25 16:50:13 CST; 5s ago
   Main PID: 17473 (node)
      Tasks: 187 (limit: 9412)
     Memory: 324.5M
        CPU: 2.920s
     CGroup: /system.slice/cryptpad.service
             |-17473 /root/.nvm/versions/node/v22.14.0/bin/node /root/cryptpad/server.js
             |-17484 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17485 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17486 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17487 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17488 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17489 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17495 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17497 /root/.nvm/versions/node/v22.14.0/bin/node ./lib/http-worker.js
             |-17540 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker
             |-17541 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker
             |-17547 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker
             |-17548 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker
             |-17555 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker
             |-17562 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker
             |-17567 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker
             `-17571 /root/.nvm/versions/node/v22.14.0/bin/node lib/workers/db-worker

Mar 25 16:50:13 debian systemd[1]: Started cryptpad.service - CryptPad API server.
Mar 25 16:50:13 debian node[17473]: =============================
Mar 25 16:50:13 debian node[17473]: Create your first admin account and customize your instance by visiting
Mar 25 16:50:13 debian node[17473]: https://www.test.com/install/#36d0e4dca1fb70152e350774332e9ded27a5ca5a58370ba9f70254a184f28e23
Mar 25 16:50:13 debian node[17473]: =============================

成功了就会像这样,给出安装配置的URL。

但是现在还不能访问。接下来,我们要继续配置nginx。

接下来的配置涉及到证书,如果你需要自签名证书什么的,可以去看看第4节的内容。

首先,官方贴心的给我们提供了一个nginx配置模板。

# SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <[email protected]> and contributors
#
# SPDX-License-Identifier: AGPL-3.0-or-later

#   This file is included strictly as an example of how Nginx can be configured
#   to work with CryptPad. This example WILL NOT WORK AS IS. For best results,
#   compare the sections of this configuration file against a working CryptPad
#   installation (http server by the Nodejs process). If you are using CryptPad
#   in production and require professional support please contact [email protected]

server {
    listen 80;
    listen [::]:80;
    server_name your-main-domain.com your-sandbox-domain.com;

    access_log /dev/null;
    error_log /dev/null emerg;

    # Let's Encrypt webroot
    include letsencrypt-webroot;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    # Let's Encrypt webroot
    include letsencrypt-webroot;

    # CryptPad serves static assets over these two domains.
    # `your-main-domain` is what users will enter in their address bar.
    # Privileged computation such as key management is handled in this scope
    # UI content is loaded via the `your-sandbox-domain`.
    # "Content Security Policy" headers prevent content loaded via the sandbox
    # from accessing privileged information.
    # This setup allows to take advantage of CryptPad's sandboxing techniques.
    # In the event of an XSS vulnerability in CryptPad's front-end code
    # this will limit the amount of information accessible to attackers.
    server_name your-main-domain.com your-sandbox-domain.com;

    # You'll need to Set the path to your certificates and keys here
    # IMPORTANT: this config is intended to serve assets for at least two domains
    # (your main domain and your sandbox domain). As such, you'll need to generate a single SSL certificate
    # that includes both domains in order for things to work as expected.
    ssl_certificate /etc/ssl/lets-encrypt/your-main-domain.com/cert;
    ssl_certificate_key /etc/ssl/lets-encrypt/your-main-domain.com/key;

    # diffie-hellman parameters are used to negotiate keys for your session
    # generate strong parameters using the following command
    ssl_dhparam /etc/nginx/dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096

    # Speeds things up a little bit when resuming a session
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;

    # replace with the IP address of your resolver
    resolver 8.8.8.8 8.8.4.4 1.1.1.1 1.0.0.1 9.9.9.9 149.112.112.112 208.67.222.222 208.67.220.220;

    location / {
        proxy_pass            http://localhost:3000;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size  150m;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }

    location ^~ /cryptpad_websocket {
        proxy_pass            http://localhost:3003;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }
}

我们把它放到/etc/nginx/sites-enabled里面。

改的地方不是很多,你可以看一下我改的地方:

# SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <[email protected]> and contributors
#
# SPDX-License-Identifier: AGPL-3.0-or-later

#   This file is included strictly as an example of how Nginx can be configured
#   to work with CryptPad. This example WILL NOT WORK AS IS. For best results,
#   compare the sections of this configuration file against a working CryptPad
#   installation (http server by the Nodejs process). If you are using CryptPad
#   in production and require professional support please contact [email protected]

server {
    listen 80;
    listen [::]:80;
    server_name www.test.com sandbox.test.com;

    access_log /dev/null;
    error_log /dev/null emerg;

    # Let's Encrypt webroot
    #include letsencrypt-webroot;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    #http2 on;

    # Let's Encrypt webroot
    #include letsencrypt-webroot;

    # CryptPad serves static assets over these two domains.
    # `your-main-domain` is what users will enter in their address bar.
    # Privileged computation such as key management is handled in this scope
    # UI content is loaded via the `your-sandbox-domain`.
    # "Content Security Policy" headers prevent content loaded via the sandbox
    # from accessing privileged information.
    # This setup allows to take advantage of CryptPad's sandboxing techniques.
    # In the event of an XSS vulnerability in CryptPad's front-end code
    # this will limit the amount of information accessible to attackers.
    server_name www.test.com sandbox.test.com;

    # You'll need to Set the path to your certificates and keys here
    # IMPORTANT: this config is intended to serve assets for at least two domains
    # (your main domain and your sandbox domain). As such, you'll need to generate a single SSL certificate
    # that includes both domains in order for things to work as expected.
    ssl_certificate /CA/test/test_crypt.crt;
    ssl_certificate_key /CA/test/test_crypt.key;

    # diffie-hellman parameters are used to negotiate keys for your session
    # generate strong parameters using the following command
    ssl_dhparam /etc/nginx/dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096

    # Speeds things up a little bit when resuming a session
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /CA/test/test.crt;

    # replace with the IP address of your resolver
    resolver 8.8.8.8 8.8.4.4 1.1.1.1 1.0.0.1 9.9.9.9 149.112.112.112 208.67.222.222 208.67.220.220;

    location / {
        proxy_pass            http://localhost:3000;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size  150m;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }

    location ^~ /cryptpad_websocket {
        proxy_pass            http://localhost:3003;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }
}

这里我特别说一下,include letsencrypt-webroot;这个要注释掉。因为我们没有用Let’s Encrypt的证书小工具,假设你已经把证书和私钥放到了别的地方,下面改掉就是。

还有ssl那里的http2 on;同样注释,应该把http2加入到listen 443后面。

还有,cryptpad要求我们生成一个Diffie-Hellman密钥,执行这个命令即可:

openssl dhparam -out /etc/nginx/dhparam.pem 4096

注意,执行后,openssl会开始进行计算,你看到…+…..什么的就是计算过程。在一些性能一般的服务器可能需要几十分钟,你也可以用你的电脑计算生成后上传到服务器。

root@debian:/etc/nginx/sites-enabled# openssl dhparam -out /etc/nginx/dhparam.pem 4096
Generating DH parameters, 4096 bit long safe prime
.........+....................................................................................................................................................................................................................................................................................................................................................................................................+.................+.....................+.....................................................................+.........................................................................+..............................................................................................................................................................................................................................................................................+...........................................++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*

好在我的电脑还是给我面子的,一下就好了。。。

然后,启动nginx服务,如果没有问题,nginx将会反向代理cryptpad。

4.自签名证书配置(可选)

RHEL系的openssl配置文件的路径和Debian系是不一样的!尽管如此,你还是可以参考本节内容当作一个自签名证书教程。

如果你已经准备好证书,那么可以跳过这里。

如果你是内网使用或者因为一些别的原因,只能自签名证书,那么这里我给出从自签名CA到自签名证书的过程。

首先,输出一个私钥:

openssl genrsa -out test.key 4096

用私钥签名CA证书:

openssl req -x509 -new -nodes -key test.key -out test.crt -days 3650 -sha256

输出网站私钥:

openssl genrsa -out test_crypt.key 4096

新建证书请求:

openssl req -new -key test_crypt.key -out test_crypt.csr

编辑一份ext.ini,内容为:

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = test.com
DNS.2 = www.test.com
DNS.3 = *.test.com

DNS那些改成你自己要用的域名。

配置CA命令:

修改openssl配置文件

vim /etc/ssl/openssl.cnf

你应该可以看到这一段:

[ CA_default ]

dir             = ./demoCA              # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several certs with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/cacert.pem       # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/cakey.pem# The private key

x509_extensions = usr_cert              # The extensions to add to the cert

你可以按照它的说明创建文件夹,把CA的证书和私钥按照它的要求放进去,也可以自己修改位置。

比如我的:

[ CA_default ]

dir             = /CA/test              # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several certs with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/test.crt         # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/test.key # The private key

x509_extensions = usr_cert              # The extensions to add to the cert

按照配置文件创建文件和文件夹:

mkdir /CA/test/newcerts
echo 01 > /CA/test/serial
touch /CA/test/index.txt

CA签发证书:

root@debian:/CA/test# openssl ca -in test_crypt.csr -out test_crypt.crt -days 3650 -batch -extfile ext.ini -extensions v3_req
Using configuration from /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Mar 25 09:14:21 2025 GMT
            Not After : Mar 23 09:14:21 2035 GMT
        Subject:
            countryName               = CN
            stateOrProvinceName       = test
            organizationName          = test
            organizationalUnitName    = test
            commonName                = www.test.com
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:test.com, DNS:www.test.com, DNS:*.test.com
Certificate is to be certified until Mar 23 09:14:21 2035 GMT (3650 days)

Write out database with 1 new entries
Database updated

好了,以我为例,test_crypt.key是私钥,test_crypt.crt是证书。

5.CryptPad配置

后端配置成功后,访问主域名:

成功了,但是现在没有任何账号,还记得前面的配置URL吗?访问它。

这里自行设置。

这个地方看个人,如果只有你用且目的是为了对外分享,可以选择关闭注册。

整体界面

自毁之后连所有者都无法访问。

就先展示到这里,有什么功能你可以自己去看看。

6.一些说明

为什么不在docker里搭建?

事实上我也想,但是我的服务器用的是openresty,平常用面板管理。虽然也可以反向代理,但是控制台会出现CSP错误,这就导致cryptpad一直卡在界面加载过程。

然后我又懒得去动openresty了,不然到时候又把别的服务搞崩溃。所以建议直接用nginx,然后用上面的官方示例配置文件。

至于这个服务本身,它不能直接导入docx,所以如果要记录点东西,我推荐markdown存储。

看着还行

7.参考文章

我也是看了别的文档,然后整合出这篇教程的。

官方文档:https://docs.cryptpad.org/en/admin_guide/index.html

https://cn.linux-console.net/?p=30800

作者信息:

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇