Read the latest posts from Fedi.dev.

from Gytis Repečka

WordPress content management system can successfully federate – there is a nice ActivityPub plugin. However, when running WordPress on Nginx server (as HTTP server, not only reverse proxy) there might be an issue – after setting up ActivityPub on auto.coffee I couldn't find @gytis@auto.coffee from my Mastodon instance.

After doing some digging I found out ActivityPub standard requires webfinger end-point under .well-known folder which by proposed default WordPress configuration for Nginx is forbidden.

First I tried to allow access to .well-known but even though JSON API started working, trying to access specific user end-point it kept throwing following error:

  "code": "rest_missing_callback_param",
  "message": "Missing parameter(s): resource",
  "data": {
    "status": 400,
    "params": [

While following example of successfully federating WordPress instance it was expected to return something like this:

  "subject": "acct:gytis@blog.gyt.is",
  "aliases": [
  "links": [
      "rel": "self",
      "type": "application/activity+json",
      "href": "https://blog.gyt.is/author/gytis/"
      "rel": "http://webfinger.net/rel/profile-page",
      "type": "text/html",
      "href": "https://blog.gyt.is/author/gytis/"

Actually problem was that URL was not passed to WordPress' index.php – workaround was provided in issue #8 of ActivityPub plugin. Solution is easy as adding extra location directive in Nginx configuration:

location ~* /.well-known {
    try_files $uri $uri/ /index.php?$args;

And there it goes – Auto.Coffee is ready to federate :)

Read more #server and #nginx #configuration tips.


from Gytis Repečka

Remember legendary MK3 on 16-bit Sega Mega Drive (Genesis in US)? Use following cheats in start menu to enable extra options.

Use Enter
Smoke, bosses (2nd player), hidden game C A A C A
Secrets menu B A A C
Cheats menu A C B B A

More about MK3 on GameFAQs.

Tags: #gaming #sega #16bit #mk3


from Gytis Repečka

WriteFreely is open source, lightweight blogging platform written in Go programming language.

Motivation to build WriteFreely

While absolute king of blogs is WordPress, which in fact powers somewhat 30% of all websites, some say it is overloaded, choosing perfect theme is extremely difficult and some (especially free) plugins are poisoned with different kinds of tracking. I do use WordPress on my main site as well, but over the years I' ve figured it seriously takes time to post an article (and I'm not yet even aquainted with Gutenberg).

WriteFreely here is a nice alternative claiming to offer a distraction-free writing experience. While supporting HTML, software mainly relies and endorses markdown. I do not plan ditching WordPress anytime soon, but I was very curious to try out lightweight platform that natively federates.


This guide details how to build decent version of WriteFreely from source on CentOS 7 machine.

Instructions should work for other Linux distributions as well but bear in mind that some paths and details (yum vs. apt, etc.) might differ across systems.


Version 1.10+ is required. Download from Go website or (preferably) install using package manager:

yum install golang go-bindata

At the time of writing sufficient version was available on standard repository:

go version go1.11.5 linux/amd64


Make sure EPEL repository is installed:

yum install epel-release

Install Node.js and package manager npm:

yum install nodejs npm


Less.js (source) is needed to convert Less stylesheets to CSS.

npm install -g less
/usr/bin/lessc -> /usr/lib/node_modules/less/bin/lessc
- ycssmin@1.0.1 node_modules/less/node_modules/ycssmin
└── less@3.9.0 

npm install -g less-plugin-clean-css
└── less-plugin-clean-css@1.5.1

From above output make sure to remember /usr/bin/lessc – we will need it later.

MySQL or MariaDB

WriteFreely requires MySQL (MariaDB) 5.6+. This can be an issue with CentOS / RHEL as at the time of writing it was shipping version 5.5 which fails database initialization script on tables accesstokens, appcontent, posts and users. See my comment on issue #22.

Possible solution would be adding official MariaDB repository and installing decent version (v. 10 at the time of writing).

Create system user to run WriteFreely

For security reasons it is well worth creating unprivileged system user to run Write freely. Create new user executing:

adduser writefreely

Up to this point we've been using root or sudo user to install prerequisites. Below commands should be run under unprivileged user. Switch to it by running:

su - writefreely

Make sure user has following paths in ~/.bash_profile:

export GOBIN="$HOME/go/bin"
export GOPATH="$HOME/go/src"

If not, add them and propagate those changes:

source /etc/profile && source ~/.bash_profile

Ready to start building

ArchLinux has WriteFreely packaged – page provides good summary of dependencies. Anyhow at this point you should be good to go with prerequisites to start building.

Download WriteFreely sources

Pull sources from GitHub:

go get -d -u -v github.com/writeas/writefreely/cmd/writefreely

Parameters explained below:

-d - do not build after downloading
-u - update
-v - verbose for details

Sources of WriteFreely and included libraries should now be available at ~/go/src/src/github.com/writeas/writefreelycd into this folder.

Starting version 0.9 it is needed to explicitly tell to build with modules:

# If running Go 1.11+
export GO111MODULE=on

Otherwise such error would come up with next step:

../../sitemap.go:23:22: not enough arguments in call to stm.NewSitemap
	have ()
	want (int)
../../sitemap.go:78:4: index must be non-negative integer constant
../../sitemap.go:78:4: cannot use p.Post.Slug.NullString.String (type string) as type []interface {} in array or slice literal
../../sitemap.go:79:4: index must be non-negative integer constant
../../sitemap.go:79:18: cannot use "weekly" (type string) as type []interface {} in array or slice literal
../../sitemap.go:80:4: index must be non-negative integer constant
../../sitemap.go:80:4: cannot use true (type bool) as type []interface {} in array or slice literal
../../sitemap.go:81:4: index must be non-negative integer constant
../../sitemap.go:81:4: cannot use p.Post.Updated (type time.Time) as type []interface {} in array or slice literal
../../sitemap.go:86:33: index must be non-negative integer constant
../../sitemap.go:86:33: too many errors
make: *** [build] Error 2

Go ahead and make:

make build   # Compile the application

At this point writefreely executable should be created at ~/go/src/src/github.com/writeas/writefreely/cmd/writefreely. Don't cd into that directory directly but run config.ini creation wizard:

./cmd/writefreely/writefreely --config # Create configuration file

Above step is not needed if you are updating from previous version – in such case keep config.ini file from ~/go/src/src/github.com/writeas/writefreely!

If doing fresh install, initialize database:

# (if you chose Multi-user setup) Import the schema with:
./cmd/writefreely/writefreely --init-db

Or upgrade if was running WriteFreely before:

./cmd/writefreely/writefreely  --migrate

Proceed with installation:

make install # Generates encryption keys; installs LESS compiler

At this point we need to generate CSS files. Problem is that LESS compiler Makefile needs little commenting – edit file less/Makefile leaving lessc path:

# ifeq ($(shell which lessc),/usr/bin/lessc)
# else
#	LESSC=node_modules/.bin/lessc

I didn't have time to fix script yet, but on my system make ui was referring to node_modules/.bin/lessc instead of /usr/bin/lessc therefore error was thrown. So with modification it is good to go:

make ui # Generates CSS (run this whenever you update your styles)

Update on lessc issue: I have filled a pull request to include /bin/lessc to less/Makefile. When it is accepted, above manual fix will not be needed.

And to check if application runs:

make run     # Runs the application

If application is running, quit it by hitting CTRL+C and set up system service. Before that just make sure writefreely binary appears at ~/go/bin folder. Command make run should have placed it there already but if not, copy binary from cmd/writefreely.

Install system service

Define system service in file /etc/systemd/system/writefreely.service:

Description=Write Freely Instance
After=syslog.target network.target

; run as writefreely user


Pay attention – service should run under unprivileged user!

Now service can be started:

systemctl start writefreely

Setup reverse proxy (Nginx)

Nginx texmplate from WriteFreely guide should be good to go:

server {
    listen 80;
    listen [::]:80;

    server_name example.com;

    gzip on;
    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_redirect off;

    location ~ ^/(css|img|js|fonts)/ {
        root /var/www/example.com/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_redirect off;

This is default for unsecure connection on port 80. I recomment setting up WriteFreely on secure server block and redirect port 80 connections (both with and without www.) as well as secure connection with www. to straightforward instance domain – in my case it is fedi.dev.


If SELinux is enabled in your CentOS / RHEL installation (default), below error will pop up in Nginx error log:

2019/03/02 01:19:46 [crit] 4508#0: *1 connect() to failed (13: Permission denied) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: fedi.dev, request: "GET / HTTP/1.1", upstream: "",host: "fedi.dev"

In /var/log/audit/audit.log this message will follow:

type=AVC msg=audit(1551482556.752:6031): avc:  denied  { name_connect } for  pid=4576 comm="nginx" dest=8080 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket permissive=0

Create an exception by running:

setsebool httpd_can_network_connect on -P

That's it, you have successfully built and launched WriteFreely on CentOS :)

My fork

I do have a fork of WriteFreely on GitHub for pull request purposes. While there is no good reason you might clone from my repository instead of official one, for the reference here it is:

go get -d -u -v code.gyt.is/writefreely

Notice I use code.gyt.is as placeholder. It is nothing but static website with few meta tags to tell go get where to pull code from. In essence it actually points to my repository on GitHub, but just in case I want to switch to (most likely) on-premises Gitea, I won't need to update this documentation. Sources are pulled to following folder then:


Also I use branch fedi-dev – on it at the moment I have removed hotlinked video from landing page. So if using my repository, make sure to switch to this branch:

git checkout fedi-dev

And start building from here.

Further reading


Comments or any feedback? Toot me @gytis@mastodon.lt or contact. My all fediverse handles here.


Tags: #server #go #golang #less #build #writefreely #nginx


from Gytis Repečka

You might have already noticed I use Mastodon for my main fediverse handle @gytis@mastodon.lt. Just recently version 2.8.0 was released – see what's new there or on GitHub.

While typically updating Mastodon is quite straightforward, this time I needed to iterate Ruby version on the server as well.

That was visible from error thrown:

rbenv: version `2.6.1' is not installed (set by live/.ruby-version)

So the full upgrade sequence is following:

Retrieve Mastodon source updates

Switch or login to user which is running Mastodon and execute following:

cd ~/live
git fetch --tags
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)

You might get error here:

error: Your local changes to the following files would be overwritten by checkout:
Please commit your changes or stash them before you switch branches.

In that case reset git:

git reset --hard

And try checkout again.

Update Ruby

cd ~/.rbenv/plugins/ruby-build
git pull
cd ~/.rbenv
rbenv install 2.6.1

This was also documented in issue 638.

Update Mastodon

cd ~/live

Update Ruby dependencies

bundle install --deployment --without development test

Possible error

When recently updating mastodon.lt to Mastodon version 2.8.2 I got following error:

Warning: the running version of Bundler (1.17.2) is older than the version that created the lockfile (1.17.3). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`.

Fix it by running:

cd ~/.rbenv
gem install bundler

And go back to previous folder:

cd ~/live

Update node.js dependencies

yarn install --pure-lockfile

Database schema updates

RAILS_ENV=production bundle exec rails db:migrate

Pre-compiling updated assets

RAILS_ENV=production bundle exec rails assets:precompile

Restart services

Mastodon runs in memory so you will need to restart it for any of the previous updates to take effect.

Switch to root or run in sudo:

systemctl restart mastodon-*.service

Or restart services separately:

systemctl restart mastodon-web
systemctl restart mastodon-sidekiq
systemctl restart mastodon-streaming

There we go – Mastodon 2.8.0 with polls functionality running fine 😊 Try out my poll about Go code retrieval 👍

Updated 2019-05-17: added possible error when updating to version 2.8.2.

Tags: #mastodon #server #ruby


from Gytis Repečka

As CentOS still ships MariaDB 5.5, some users might still have an issue initializing WriteFreely's schema.sql.


./writefreely --init-db

returns following including errors:

2019/03/02 02:14:49 Loading config.ini configuration...
2019/03/02 02:14:49 Connecting to mysql database...
2019/03/02 02:14:49 Creating table accesstokens...
ERROR: 2019/03/02 02:14:49 log.go:26: Error 1067: Invalid default value for 'created'
2019/03/02 02:14:49 Creating table appcontent...
ERROR: 2019/03/02 02:14:49 log.go:26: Error 1067: Invalid default value for 'updated'
2019/03/02 02:14:49 Creating table appmigrations...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table collectionattributes...
2019/03/02 02:14:49 Created. 2019/03/02 02:14:49
Creating table collectionkeys...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table collectionpasswords...
2019/03/02 02:14:49 Created. 2019/03/02 02:14:49
Creating table collectionredirects...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table collections...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table posts...
ERROR: 2019/03/02 02:14:49 log.go:26: Error 1293: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
2019/03/02 02:14:49 Creating table remotefollows...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table remoteuserkeys...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table remoteusers...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table userattributes...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table userinvites...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Creating table users...
ERROR: 2019/03/02 02:14:49 log.go:26: Error 1067: Invalid default value for 'created'
2019/03/02 02:14:49 Creating table usersinvited...
2019/03/02 02:14:49 Created.
2019/03/02 02:14:49 Updating appmigrations table...
2019/03/02 02:14:49 Done.

In my initial installation on fedi.dev I have modified tables accesstokens, appcontent, posts and users to match MariaDB 5.5 requirements, but probably it makes no sense request them pulled as newer MariaDB/MySQL versions doesn't need any modifications to original schema.sql.

I can confirm that with MariaDB 10.x there are no issues – tables gets created successfully.

There is an issue already registered on GitHub where I also replied with these details.

Tags: #server #writefreely #writeas #golang