Perlite is an awesome project by sec77 to display your obsidian notes on the web, essentially an alternative to the paid Obsidian publish.
You'll need nginx and php8.2 and some dependencies:
[ 10.8.0.2/24 ] [ home ] [/srv]
→ apt install nginx php8.2-fpm php-mbstring php-yaml -y
[ 10.8.0.2/24 ] [ home ] [/srv]
→ vim /etc/nginx/sites-available/perlite.nowhere.moe.conf
Then we can git clone the project wherever, i put it in /srv/:
[ 10.8.0.2/24 ] [ home ] [/srv/perlite]
→ git clone https://github.com/secure-77/Perlite
[ 10.8.0.2/24 ] [ home ] [/srv/]
→ chown -R www-data: /srv/Perlite
[ 10.8.0.2/24 ] [ home ] [/srv/]
→ cd Perlite
Now from here you will need the following nginx config:
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite]
→ cat /etc/nginx/sites-available/perlite.nowhere.moe.conf
server {
#apt install apache2-utils -y
#htpasswd -c /etc/nginx/auth/default.htpasswd nothing
auth_basic "Password protection";
auth_basic_user_file /etc/nginx/auth/default.htpasswd;
server_name perlite.nowhere.moe;
root /srv/Perlite/perlite/;
index index.php index.html index.htm;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
location ~ /\.ht {
deny all;
}
location ~* ^/(.*)/.obsidian/appearance.json$ {
allow all;
}
location ~* ^/(.*)/.obsidian/(.*)/theme.css$ {
allow all;
}
#added for this specific setup, thanks sec77!
location ~* ^/.obsidian/(.*)/theme.css$ {
allow all;
}
location ~ \.(git|github|obsidian|trash) {
deny all;
}
location ~ \.(md|json)$ {
deny all;
}
}
For now it's just on port 80, and with a basicauth because i want it to be in maintenance mode for now, then we go into the perlite folder:
[ 10.8.0.2/24 ] [ home ] [/srv]
→ cd Perlite
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite]
→ ls -lash
total 72K
4.0K drwxr-xr-x 7 root root 4.0K Dec 7 22:20 .
4.0K drwxr-xr-x 7 root root 4.0K Dec 7 22:20 ..
4.0K drwxr-xr-x 8 root root 4.0K Dec 7 22:20 .git
4.0K -rw-r--r-- 1 root root 66 Dec 7 22:20 .gitattributes
4.0K drwxr-xr-x 3 root root 4.0K Dec 7 22:20 .github
4.0K -rw-r--r-- 1 root root 118 Dec 7 22:20 .gitignore
8.0K -rw-r--r-- 1 root root 4.4K Dec 7 22:20 Changelog.md
4.0K drwxr-xr-x 7 root root 4.0K Dec 7 22:20 Demo
4.0K -rw-r--r-- 1 root root 2.0K Dec 7 22:20 Docker.md
4.0K -rw-r--r-- 1 root root 1.1K Dec 7 22:20 LICENSE
8.0K -rw-r--r-- 1 root root 6.7K Dec 7 22:20 README.md
4.0K -rw-r--r-- 1 root root 182 Dec 7 22:20 SECURITY.md
4.0K -rw-r--r-- 1 root root 565 Dec 7 22:20 docker-compose-dev.yml
4.0K -rw-r--r-- 1 root root 522 Dec 7 22:20 docker-compose.yml
4.0K drwxr-xr-x 5 root root 4.0K Dec 7 22:21 perlite
4.0K drwxr-xr-x 3 root root 4.0K Dec 7 22:20 web
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite]
→ cd perlite
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite/perlite]
→ ls -lash
total 216K
4.0K drwxr-xr-x 5 root root 4.0K Dec 7 22:21 .
4.0K drwxr-xr-x 7 root root 4.0K Dec 7 22:20 ..
4.0K drwxr-xr-x 2 root root 4.0K Dec 7 22:20 .js
4.0K drwxr-xr-x 4 root root 4.0K Dec 7 22:20 .styles
4.0K -rw-r--r-- 1 root root 508 Dec 7 22:20 Dockerfile
4.0K -rw-r--r-- 1 root root 151 Dec 7 22:20 Dockerfile.dev
4.0K drwxr-xr-x 6 root root 4.0K Dec 7 22:21 Obsidian
44K -rw-r--r-- 1 root root 42K Dec 7 22:20 Parsedown.php
12K -rw-r--r-- 1 root root 11K Dec 7 22:20 PerliteParsedown.php
8.0K -rw-r--r-- 1 root root 4.3K Dec 7 22:20 content.php
16K -rw-r--r-- 1 root root 16K Dec 7 22:20 favicon.ico
12K -rw-r--r-- 1 root root 12K Dec 7 22:21 helper.php
56K -rw-r--r-- 1 root root 54K Dec 7 22:20 index.php
20K -rw-r--r-- 1 root root 17K Dec 7 22:20 logo.svg
20K -rw-r--r-- 1 root root 17K Dec 7 22:20 perlite.svg
This is where the root of the website will be. In here you can put your vault as a sub-folder, here i put mine as the "Obsidian" folder as you can see above. Before you put it there, you will need to do a few things. First of all you need the Obsidian plugin "Metadata Extractor" to get the generated metadata.json file, along with the enabled "write JSON files automatically when Obsidian Launches" option:
[ 10.8.0.2/24 ] [ home ] [Perlite/perlite/Obsidian]
→ ls -lash
total 260K
4.0K drwxr-xr-x 6 root root 4.0K Dec 7 22:21 .
4.0K drwxr-xr-x 5 root root 4.0K Dec 7 22:21 ..
4.0K drwxr-xr-x 8 root root 4.0K Dec 7 22:21 .git
4.0K drwxr-xr-x 4 root root 4.0K Dec 7 22:21 .obsidian
4.0K drwxr-xr-x 15 root root 4.0K Dec 7 22:21 HTB
0 -rw-r--r-- 1 root root 0 Dec 7 22:21 README.md
4.0K drwxr-xr-x 3 root root 4.0K Dec 7 22:21 Sysadmin
228K -rw-r--r-- 1 root root 225K Dec 7 22:21 metadata.json
4.0K -rwxr-xr-x 1 root root 85 Dec 7 22:21 pull.sh
4.0K -rwxr-xr-x 1 root root 207 Dec 7 22:21 push.sh
Then you need to have the New link format option set to relative path to file (it's in the Files & Links menu in obsidian settings:
For further tweaking, please look at sec77's documentation here
From here you should already see your website as follows:
[ 10.8.0.2/24 ] [ home ] [Perlite/perlite/Obsidian]
→ systemctl restart php8.2-fpm nginx
(big thanks to sec77 for showing me the fix here), If your theme doesn't load or if the vault doesnt show up, you can manually set the root directory of the vault in the helper.php file:
10.8.0.2/24 ] [ home ] [/srv/Perlite/perlite]
→ cat helper.php| grep rootDir
//$rootDir = getenv('NOTES_PATH');
$rootDir = 'Obsidian';
$vaultName = $rootDir;
[...]
Here you see i setup mine to the relative path 'Obsidian' which points to the subdirectory in /srv/Perlite/perlite/Obsidian/. And there you go!
If you want it setup with TLS just use acme.sh:
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite/perlite]
→ acme.sh --issue --standalone -d perlite.nowhere.moe -k 4096
[Wed Dec 7 22:59:59 CET 2022] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Wed Dec 7 22:59:59 CET 2022] Standalone mode.
[Wed Dec 7 22:59:59 CET 2022] Creating domain key
[Wed Dec 7 23:00:00 CET 2022] The domain key is here: /root/.acme.sh/perlite.nowhere.moe/perlite.nowhere.moe.key
[Wed Dec 7 23:00:00 CET 2022] Single domain='perlite.nowhere.moe'
[Wed Dec 7 23:00:00 CET 2022] Getting domain auth token for each domain
[Wed Dec 7 23:00:03 CET 2022] Getting webroot for domain='perlite.nowhere.moe'
[Wed Dec 7 23:00:04 CET 2022] Verifying: perlite.nowhere.moe
[Wed Dec 7 23:00:04 CET 2022] Standalone mode server
[Wed Dec 7 23:00:06 CET 2022] Pending, The CA is processing your order, please just wait. (1/30)
[Wed Dec 7 23:00:09 CET 2022] Success
[...]
[Wed Dec 7 23:00:12 CET 2022] Your cert is in: /root/.acme.sh/perlite.nowhere.moe/perlite.nowhere.moe.cer
[Wed Dec 7 23:00:12 CET 2022] Your cert key is in: /root/.acme.sh/perlite.nowhere.moe/perlite.nowhere.moe.key
[Wed Dec 7 23:00:12 CET 2022] The intermediate CA cert is in: /root/.acme.sh/perlite.nowhere.moe/ca.cer
[Wed Dec 7 23:00:12 CET 2022] And the full chain certs is there: /root/.acme.sh/perlite.nowhere.moe/fullchain.cer
and then for the nginx config with TLS I use the following:
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite/perlite]
→ cat /etc/nginx/sites-available/perlite.nowhere.moe.conf
server {
listen 80;
listen [::]:80;
server_name perlite.nowhere.moe;
return 301 https://$server_name$request_uri;
}
server {
######## TOR CHANGES ########
listen 4443;
listen [::]:4443;
server_name perlite.nihilisxacas2ntt3kb2nzfjp4nu5enratyehvahllblxgq2tqpsrnid.onion;
add_header Onion-Location "http://perlite.nihilisxacas2ntt3kb2nzfjp4nu5enratyehvahllblxgq2tqpsrnid.onion$request_uri" always;
######## TOR CHANGES ########
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name perlite.nowhere.moe;
ssl_certificate /root/.acme.sh/perlite.nowhere.moe/fullchain.cer;
ssl_trusted_certificate /root/.acme.sh/perlite.nowhere.moe/perlite.nowhere.moe.cer;
ssl_certificate_key /root/.acme.sh/perlite.nowhere.moe/perlite.nowhere.moe.key;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers 'TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_ecdh_curve auto;
ssl_stapling on;
ssl_stapling_verify on;
resolver 80.67.188.188 80.67.169.40 valid=300s;
resolver_timeout 10s;
add_header X-XSS-Protection "1; mode=block"; #Cross-site scripting
add_header X-Frame-Options "SAMEORIGIN" always; #clickjacking
add_header X-Content-Type-Options nosniff; #MIME-type sniffing
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
root /srv/Perlite/perlite/;
index index.php index.html index.htm;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
location ~ /\.ht {
deny all;
}
location ~* ^/(.*)/.obsidian/appearance.json$ {
allow all;
}
location ~* ^/(.*)/.obsidian/(.*)/theme.css$ {
allow all;
}
#added for this specific setup, thanks sec77!
location ~* ^/.obsidian/(.*)/theme.css$ {
allow all;
}
location ~ \.(git|github|obsidian|trash) {
deny all;
}
location ~ \.(md|json)$ {
deny all;
}
}
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite/perlite]
→ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[ 10.8.0.2/24 ] [ home ] [/srv/Perlite/perlite]
→ systemctl restart nginx
And there you go! We have been able to publish our obsidian notes on the web from our a VPS.
Donate XMR: 8AUYjhQeG3D5aodJDtqG499N5jXXM71gYKD8LgSsFB9BUV1o7muLv3DXHoydRTK4SZaaUBq4EAUqpZHLrX2VZLH71Jrd9k8
Contact: nihilist@contact.nowhere.moe (PGP)