Installing a WriteFreely weblog
I have been using WordPress ever since I decided to have a personal website/blog. It has served me well but I've come to a point where I got tired of messing with plugin conflicts, and spammers. I also like Markdown a lot and the available plugins for WordPress were either broken or had conflicts with other plugins. So I decided to try something simpler. At first I had my mind on static generators but then I came across WriteFreely, a minimalistic, distributed and customizable blogging software. It supports Markdown and HTML and that's all I need right now. On the minus side, it does not support media uploads but we will show a workaround to that, on this guide.
Prerequisites
- A Debian buster system (Ubuntu or other Debian derivatives should work too.)
- Install dependencies:
# apt install nginx mariadb-server certbot python3-certbot-nginx
- Some domains like example.org, www.example.org and media.example.org:
www.example.org. 300 IN CNAME example.org.
media.example.org. 300 IN CNAME example.org.
example.org. 300 IN A 1.2.3.4
- Remove skip-name-resolve from /etc/mysql/mariadb.conf.d/50-server.cnf and restart MariaDB [2]:
$ sudo sed -i -r -e 's/(skip-name-resolve)/#\1/' /etc/mysql/mariadb.conf.d/50-server.cnf && \
sudo systemctl restart mariadb
Setup WriteFreely
- Create a writefreely system user:
$ sudo useradd -r -m -d /srv/writefreely writefreely
- Download and extract WriteFreely:
$ sudo su - writefreely
$ wget https://github.com/writeas/writefreely/releases/download/v0.12.0/writefreely_0.12.0_linux_amd64.tar.gz
$ tar xvzf writefreely_0.12.0_linux_amd64.tar.gz
$ mv writefreely example.org
- Prepare the database:
$ sudo mysql
MariaDB [(none)]> CREATE DATABASE writefreely;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON writefreely.* TO 'writefreelyuser'@'localhost' IDENTIFIED BY 'MySecretDBPass';
- Generate the config file:
$ ./writefreely --create-config
- Apply the following changes in the generated config.ini file:
--- config.ini.orig 2020-08-08 13:57:13.377920751 +0300
+++ config.ini.new 2020-08-08 14:56:48.032964841 +0300
@@ -14,16 +14,16 @@
[database]
type = mysql
filename =
-username =
-password =
-database =
+username = writefreelyuser
+password = MySecretDBPass
+database = writefreely
host = localhost
port = 3306
[app]
-site_name =
-site_description =
-host = http://localhost:8080
+site_name = Roasted Chickpeas Downhill
+site_description = Roll those Chickpeas!
+host = https://example.org
theme = write
editor =
disable_js = false
@@ -43,7 +43,7 @@
private = false
local_timeline = false
user_invites =
-default_visibility =
+default_visibility = unlisted
update_checks = false
[oauth.slack]
If you prefer a multiuser site you can change the single_user
directive to false. You can also choose how many blogs per user with max_blogs
. A full list of list of configuration options from the WriteFreely config documentation page.
NOTE: I noticed that .using
./writefreely config start
hungs at some steps so you may want to avoid that until the problem is resolved.
- Initialize the database:
$ ./writefreely db init
- Generate encryption keys:
$ ./writefreely keys generate
- Create an admin user:
$ ./writefreely --create-admin admin:MySecretAdminPass
Create a WriteFreely service:
Create a systemd service file (/etc/systemd/system/writefreely.service):
[Unit]
Description=WriteFreely Instance
After=syslog.target network.target mysql.service
[Service]
Type=simple
StandardOutput=syslog
StandardError=syslog
User=writefreely
Group=writefreely
WorkingDirectory=/srv/writefreely/example.org
ExecStart=/srv/writefreely/example.org/writefreely
Restart=always
[Install]
WantedBy=multi-user.target
- Enable and start the service:
$ systemctl daemon-reload
$ systemctl enable --now writefreely.service
- Verify :
# systemctl status writefreely.service ; echo; ss -lnptu | grep writefreely
● writefreely.service - WriteFreely Instance
Loaded: loaded (/etc/systemd/system/writefreely.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2020-08-02 11:18:43 EEST; 46s ago
Main PID: 20540 (writefreely)
Tasks: 16 (limit: 4915)
Memory: 18.3M
CGroup: /system.slice/writefreely.service
└─20540 /srv/writefreely/freely.theo-andreou.org/writefreely
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Loading config.ini configuration...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Loading templates...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Loading pages...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Loading user pages...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Loading encryption keys...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Connecting to mysql database...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Adding {domain} routes (single user)...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Going to serve...
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 Serving on http://localhost:8080
Aug 02 11:18:43 galadriel writefreely[20540]: 2020/08/02 11:18:43 ---
tcp LISTEN 0 128 127.0.0.1:8080 0.0.0.0:\* users:(("writefreely",pid=20540,fd=5))
Setup the Reverse Proxy
- Prepare an Nginx virtualhost file (/etc/nginx/site-available/example.org):
server {
listen 80;
listen [::]:80;
server_name example.org www.example.org;
gzip on;
gzip_types
application/javascript
application/x-javascript
application/json
application/rss+xml
application/xml
image/svg+xml
image/x-icon
application/vnd.ms-fontobject
application/font-sfnt
text/css
text/plain;
gzip_min_length 256;
gzip_comp_level 5;
gzip_http_version 1.1;
gzip_vary on;
location ~ ^/.well-known/(webfinger|nodeinfo|host-meta) {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
}
location ~ ^/(css|img|js|fonts)/ {
root /srv/writefreely/example.org/static;
# Optionally cache these files in the browser:
# expires 12M;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
}
}
- Enable the virtualhost:
$ cd /etc/nginx/sites-enabled/
$ sudo ln -s ../sites-available/example.org
$ sudo nginx -t && sudo systemctl reload nginx
- Enable TLS on the virtualhost:
# certbot run --nginx --agree-tos -m me@example.org --redirect -n -d example.org
Now visit https://example.org to use your newlly created WriteFreely Blog
Customizing the Look and Feel
If you want to change the way your blog looks you can use the Customize option after you login. Under Custom CSS you can use add you own CCS. Mine is based on the Dark Theme with some additional twaeks. Feel free to use it as you wish:
/*
Written in 2020 by Theodotos Andreou (based on the Dark Theme by Write.as)
To the extent possible under law, the author(s) have dedicated all
copyright and related and neighboring rights to this software to the
public domain worldwide. This software is distributed without any
warranty.
You should have received a copy of the CC0 Public Domain Dedication
along with this software. If not, see
http://creativecommons.org/publicdomain/zero/1.0
*/
body {
color: #eee;
background: #111;
}
body .post-title a:link, a:visited {
color: #ccc;
}
#collection #wrapper pre {
background: #393e46;
}
#collection #wrapper code {
background: #393e46;
}
#collection code {
background-color: #393e46;
}
#collection .post-title a {
color: #ccc;
}
#collection {
color: #eee;
}
body h1 a, body header h2 a {
color: #cfcfcf;
}
body h1 a:hover, body header h2 a:hover {
color: #fff;
}
body h1 a:visited, body header h2 a:visited {
color: #ccc;
}
body #manage ul a, body .dropdown-nav ul a, body #manage ul ul a, body #manage ul a {
color: #ccc;
}
body .dropdown-nav ul ul, body .dropdown-nav ul li:hover, body #manage ul ul, body #manage ul ul li:hover, body #manage ul li:hover {
background: #222;
}
body #official-writing h2, body #official-writing h3, body #official-writing h4, body #wrapper h2, body #wrapper h3, body #wrapper h4 {
color: #ddd;
}
body a {
color: #f6fccd;
}
body a:visited {
color: #f6fcb0;
}
body #official-writing h2, body #official-writing h3, body #official-writing h4, body #wrapper h2, body #wrapper h3, body #wrapper h4 {
color: #aaa;
}
body #official-writing ul.collections li.collection a.title:link, body #official-writing ul.collections li.collection a.title:visited, body #wrapper ul.collections li.collection a.title:link, body #wrapper ul.collections li.collection a.title:visited {
color: #cfcfcf;
}
body #official-writing ul.collections li a.create, body #wrapper ul.collections li a.create {
color: #aaa;
}
body#me #official-writing h2 a:link, body#me #official-writing h2 a:visited {
color: #a2a2ff;
}
header p.description {
color: #fcfcfc;
}
header .pinned {
color: #f6fccd;
}
body p.code {
background: #f6fcb0;
}
body header nav a:visited {
color: #f6fcb0;
}
body header article code {
background: #ff0000;
}
body pre {
background: #f6fcb0;
}
body footer nav {
color: #fcfcfc;
}
input {
background: #202020;
color: #bbb;
}
#manage ul ul li img {
filter: invert(1);
}
#post code, #collection code, #subpage code {
background: #202020;
color: #33ff33;
}
body#collection pre, body#post pre, body#subpage pre {
background: #393e46;
}
body#collection code, body#post code, body#subpage code {
background: #393e46;
}
I am a total illiterate when it comes to CCS and the above tweaks came out of tedious trial and error. If you see anything that can be improved feel free to contact me.
Uploading media
Since WriteFreely does not support media uploads we will be using a separate domain for that (e.g. media.example.org) and we will be uploading files on that site using traditional upload methods like ftp, scp or sftp. Then we can reference those images using MarkDown syntax.
- Prepare the Media store:
$ sudo mkdir /srv/media
Upload a file to it, let's say /srv/media/sample.jpg.
- Prepare the Nginx virtualhost (/etc/nginx/sites-anailable/media.example.org):
server {
listen 80;
listen [::]:80;
root /srv/media;
server_name media.example.org;
location / {
try_files $uri $uri/ =404;
}
}
- Enable the virtualhost:
$ cd /etc/nginx/sites-enabled/
$ sudo ln -s ../sites-available/media.example.org
$ sudo nginx -t && sudo systemctl reload nginx
- Enable TLS on the virtualhost:
$ sudo certbot run --nginx --agree-tos -m me@example.org --redirect -n -d media.example.org
Now you can referemce your image using:
![Image name](https://media.example.org/sample.jpg "Image Alt text")
References
- https://writefreely.org/start
- https://github.com/writeas/writefreely/issues/246#issuecomment-577553211
License
This work is licensed under a Creative Commons Attribution 4.0 International License
#writefreely #nginx #mariadb #linux #debian #freesoftware #blog #cms #activitypub #fediverse #distributed