
Why I migrated my blog from Ghost to WriteFreely and how you can do it too
Why WriteFreely?
After years with various blogging platforms, I was looking for something simpler. Ghost was great, but:
- ✅ Native ActivityPub Integration - My blog is automatically available in the Fediverse
- ✅ Minimal Resource Usage - Single binary, no Node.js, no complex infrastructure
- ✅ Focus on Writing - No distractions, just writing
- ✅ Self-hosted - Full control over my data
- ✅ Markdown-native - No formatting battles
Setup: WriteFreely on LXC (Proxmox)
Why Native Installation Instead of Docker?
After several frustrating hours with Docker mount problems, I decided on native installation. Best decision ever!
# Download WriteFreely binary
cd /opt
wget https://github.com/writefreely/writefreely/releases/download/v0.15.0/writefreely_0.15.0_linux_arm64.tar.gz
tar -xzf writefreely_0.15.0_linux_arm64.tar.gz
mv writefreely /opt/writefreely
cd /opt/writefreely
# Interactive configuration
./writefreely --config
Configuration (config.ini)
[server]
bind = 0.0.0.0 # Important for reverse proxy
port = 8080
https = false # Reverse proxy handles HTTPS
[app]
site_name = My Blog
host = https://blog.example.com # Your real domain!
single_user = true
federation = true # This is the key!
public_registration = false
[database]
type = sqlite3 # Simpler than MySQL for single user
filename = writefreely.db
As systemd Service
# Create service file
sudo tee /etc/systemd/system/writefreely.service


Caption here
ActivityPub: Automatically in the Fediverse
The best thing about WriteFreely: It just works!
- My blog:
@username@blog.example.com - Followers: Automatically via Mastodon, Pleroma, etc.
- Posts: Automatically federated to the Fediverse
- Interaction: Comments via ActivityPub possible
Testing Federation
# Test WebFinger
curl https://blog.example.com/.well-known/webfinger?resource=acct:username@blog.example.com
# ActivityPub profile
curl -H "Accept: application/activity+json" https://blog.example.com/@username
Troubleshooting: Common Problems
Problem 1: Code boxes stay white
Solution: Edit WriteFreely’s write.css directly:
cd /opt/writefreely/static/css
sudo nano write.css
# Search for: background:#f8f8f8
# Replace with: background:#1e1e1e
Problem 2: CSS not applied
Solution: Aggressively clear browser cache, test different browsers.
Problem 3: ActivityPub doesn’t work
Solution:
federation = truein config.inihost = https://your-real-domain.com(not localhost!)- Reverse proxy configured correctly
Webspace for Images
Separate container for static assets:
# docker-compose.yml for webspace
services:
webspace:
image: httpd:latest
volumes:
- ./webspace:/usr/local/apache2/htdocs
labels:
- "traefik.http.routers.webspace.rule=(Host(`cdn.example.com`))"
# ... Additional labels
Conclusion: Is the Switch Worth It?
Definitely yes! After migration:
✅ Much faster - Page loads lightning fast ✅ Less maintenance - One binary, no updates, no Node.js ✅ Fediverse integration - My posts automatically reach more people ✅ Focus on writing - No distractions from complex themes/plugins ✅ Resource efficient - Runs smoothly on small LXC
Resources
- WriteFreely: https://writefreely.org
- ActivityPub Plugin (WordPress): https://wordpress.org/plugins/activitypub/
- Fediverse Test: https://fediverse.party
Credits
- Header Image by Daniel Thomas on Unsplash
Migration completed: ✅ Self-hosted, ✅ Fediverse-ready, ✅ Minimal & fast
