---
title: "Deploy Writefreely"
description: "Medium alternative. Markdown blog platform that federates over ActivityPub"
category: "Blogs"
url: https://railway.com/deploy/writefreely-blogs
---

# Deploy Writefreely

Medium alternative. Markdown blog platform that federates over ActivityPub

**[Deploy Writefreely on Railway](https://railway.com/template/writefreely-blogs)**

- **Creator:** A3A
- **Category:** Blogs
- **Total deploys:** 1

## Template content

### mailpit https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/mailpit.svg

- **Image:** axllent/mailpit:latest
- **Health check:** /livez
- **Public domain:** Yes

### writefreely https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/writefreely.svg

- **Source:** https://github.com/gridalpha/writefreely-railway
- **Health check:** /
- **Public domain:** Yes

### MySQL https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/mysql.svg

- **Image:** mysql:9.4
- **Start command:** `docker-entrypoint.sh mysqld --innodb-use-native-aio=0 --disable-log-bin --performance_schema=0 --innodb-buffer-pool-size=1G`

## Documentation

![WriteFreely logo](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQsLkWltCBKbfab22zWgC2K6bnsQh8kquwPdNGFfmx7VA&amp;s)

# Deploy and Host WriteFreely on Railway

WriteFreely is an open-source, Markdown-first publishing platform for people who want to write rather than administer a website. There are no themes to pick and no plugin marketplace — you open a page, type, and publish. Each blog is also an ActivityPub actor, so readers on Mastodon can follow it like a person, and every post carries an RSS feed. Writers' collectives, teams keeping a changelog, and people leaving Medium or Substack all use it because it is a small, quiet tool that outlives the company behind it.

Self-host WriteFreely on Railway and this template wires up the whole instance: the **WriteFreely** application built from the pinned upstream release, a managed **MySQL** database holding every account, blog and post, and a **Mailpit** service catching outgoing mail, so email subscriptions and password resets work from the first minute. Public traffic arrives over the Railway domain, the app reaches MySQL and Mailpit privately, and a volume keeps settings and keys across redeploys. Nothing needs editing by hand — the container writes its own configuration, derives its keys, creates the schema and creates your administrator account on first boot.

![WriteFreely Railway architecture](https://res.cloudinary.com/rroe4rtk/image/upload/v1787076128/0f839ce3-b146-44be-9aea-b654947cb8f8.png)

## Getting Started with WriteFreely on Railway

Set `WRITEFREELY_ADMIN_USER` and `WRITEFREELY_ADMIN_PASS` when you deploy — those become your administrator account, and there are no default credentials to change afterwards. Choose the username carefully: WriteFreely reserves about seventy-five route-like names, so `admin`, `api`, `me`, `read` and `user` are rejected, the password must not contain a colon, and the username becomes the blog's URL.

When the deployment turns green, open the Railway domain and click **Log in**. You land straight in the editor — a blank dark page with a cursor. Start a line with `# ` to set the title, write Markdown below it, then press **Publish**; the post appears on your blog at once and the **Reader** tab lists it on the instance timeline. Use `/admin/settings` to set the site title, decide whether registrations are open, and mint invite links under **Users**. Requesting `/.well-known/webfinger?resource=acct:@` confirms federation. Mail lands in Mailpit, behind the `MP_UI_AUTH` credentials.

![WriteFreely blog showing a published Markdown post](https://res.cloudinary.com/rroe4rtk/image/upload/v1787051443/writefreely-blog-post.png)
![WriteFreely distraction-free editor with a draft post](https://res.cloudinary.com/rroe4rtk/image/upload/v1787051448/writefreely-markdown-editor.png)
![WriteFreely Reader listing the instance's latest posts](https://res.cloudinary.com/rroe4rtk/image/upload/v1787051451/writefreely-reader-timeline.png)

## About Hosting WriteFreely

WriteFreely is a single Go binary serving blogs, an editor and a federation endpoint on top of a SQL database. It solves a narrow problem well: a durable place to publish that you control, without the weight of a general-purpose CMS. Teams self-host it for an engineering journal or a community of authors on one instance; individuals self-host it to own their archive.

Key features:

- Distraction-free Markdown editor with a draft-first workflow
- ActivityPub federation, so each blog is followable from Mastodon
- Multi-user instances with invite links and an instance-wide Reader
- Email subscriptions, RSS feeds and full post export
- Custom CSS, themes, password-protected blogs, and unlisted or private posts

The deployment is three services. **WriteFreely** serves reading and writing and runs its email queue in-process. **MySQL** stores everything durable — users, blogs, posts, followers, subscriptions — since post bodies live in the database, not on disk. **Mailpit** captures outgoing mail in a web inbox, and becomes a real relay once `MP_SMTP_RELAY_HOST` points at a provider. A small volume holds the config file and derived keys.

## Why Deploy WriteFreely on Railway

Railway removes the parts of self-hosting unrelated to writing.

- MySQL is provisioned, backed up and networked privately
- TLS and a public domain are issued for you
- Configuration and keys persist on a volume
- Email features work on day one, with no provider account
- Scaling memory or CPU is a slider, not a migration

## Common Use Cases

- A personal blog you own outright, followable from Mastodon
- A writers' collective running one invite-only instance with a shared Reader
- An engineering team's changelog or research journal, in Markdown
- A newsletter replacement, with readers subscribing by email

## Dependencies for WriteFreely

- **WriteFreely** — built from [github.com/writefreely/writefreely](https://github.com/writefreely/writefreely) at a pinned release tag via [github.com/gridalpha/writefreely-railway](https://github.com/gridalpha/writefreely-railway). The image `ghcr.io/writefreely/writefreely:latest` follows the `develop` branch, so this template builds the stable release instead.
- **MySQL** — Railway's managed MySQL, holding all application state. WriteFreely supports MySQL and SQLite only.
- **Mailpit** — `axllent/mailpit:latest`, accepting SMTP privately and showing captured mail in a browser inbox.

### Environment Variables Reference

| Variable | Purpose |
|---|---|
| `WRITEFREELY_HOST` | Public URL of the instance; every federation actor URL is built from it |
| `WRITEFREELY_KEYS_SECRET` | Seeds every encryption key; changing it signs everyone out |
| `WRITEFREELY_ADMIN_USER` | First administrator, and the alias of their blog |
| `WRITEFREELY_SINGLE_USER` | `true` serves one blog at the root domain |
| `WRITEFREELY_OPEN_REGISTRATION` | Whether strangers may create accounts |
| `WRITEFREELY_FEDERATION` | Turns ActivityPub on or off |

### Deployment Dependencies

- Source: [github.com/writefreely/writefreely](https://github.com/writefreely/writefreely)
- Docs: [writefreely.org/docs](https://writefreely.org/docs)
- Mailpit: [github.com/axllent/mailpit](https://github.com/axllent/mailpit)
- Runtime: Go binary on Alpine Linux; MySQL 8 or newer

## Hardware Requirements for Self-Hosting WriteFreely

| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 0.5 vCPU | 1–2 vCPU |
| RAM | 512 MB app + 512 MB MySQL | 1 GB each |
| Storage | 1 GB volume + database | 5 GB as the archive grows |
| Runtime | Go 1.25, MySQL 8+ | Same |

WriteFreely is unusually light: the binary idles in tens of megabytes, and growth is database rows rather than files, since posts are text and it hosts no uploaded media.

## Self-Hosting WriteFreely

Outside Railway, Docker Compose is quickest. A minimal `docker-compose.yml`:

```
services:
  writefreely:
    image: ghcr.io/writefreely/writefreely:v0.17.2
    ports: ["8080:8080"]
    volumes: ["./config.ini:/go/config.ini", "keys:/go/keys"]
    depends_on: [db]
  db:
    image: mysql:8
    environment:
      MYSQL_DATABASE: writefreely
      MYSQL_ROOT_PASSWORD: change-me
    volumes: ["db:/var/lib/mysql"]
volumes: {keys: {}, db: {}}
```

WriteFreely is configured by `config.ini`, not environment variables, and its schema, keys and first account come from the command line:

```
writefreely config start
writefreely keys generate
writefreely db init
writefreely user create --admin yourname:your-password
writefreely
```

Upgrading means replacing the binary and running `writefreely db migrate`. Never delete the `keys` directory — sessions and stored subscriber addresses become unreadable without it.

## Is WriteFreely Free to Self-Host?

WriteFreely is free and open source under AGPL-3.0, with no paid tier, seat limits or feature gates in the self-hosted build. Its maintainers sell a hosted service, Write.as, but the software you run here is complete. On Railway you pay only for the compute, database and storage the three services consume — modest for a personal or small-team instance.

## FAQ

**What is WriteFreely?**
An open-source, Markdown-based blogging platform with built-in ActivityPub federation. It focuses on writing rather than site administration, and is often described as a self-hosted alternative to Medium or Substack.

**What does this Railway template deploy?**
Three services: the WriteFreely application built from a pinned upstream release, a managed MySQL database, and Mailpit as an SMTP server with a web inbox. A volume keeps the app's config and keys.

**Why do MySQL and Mailpit ship with the template?**
WriteFreely supports MySQL and SQLite only, and SQLite is one file on local disk; managed MySQL gives backups and a database independent of the app container. Email subscriptions and password resets stay hidden until an SMTP server exists, so Mailpit provides one — point `MP_SMTP_RELAY_HOST` at a real provider to deliver outside.

**How do I invite other writers to my self-hosted WriteFreely instance?**
Registrations are closed by default. Sign in as the administrator, open **Users**, and generate an invite link with an optional expiry and use limit. To let strangers sign up, enable **Open Registrations** in admin settings.

**Can people follow my WriteFreely blog from Mastodon?**
Yes — federation is on by default, and each blog is an ActivityPub actor addressable as `@blogname@your-domain`. Keep the public URL stable: changing the domain later orphans existing followers, whose subscriptions point at the old address.

**How do I run a single-user blog instead of a multi-user instance?**
Set `WRITEFREELY_SINGLE_USER` to `true` before the first deployment: your blog is then served at the domain root rather than under a username, and the Reader is dropped. Decide before publishing anything.


## Similar templates

- [Pixelfed](https://railway.com/deploy/OZSdEw) — Explore + Share beautiful photos and videos on the Fediverse
- [Hexo](https://railway.com/deploy/hexo) — Hexo — fast static blog framework with admin editor and S3 media storage
- [Bluesky PDS (Atproto Spaces Alpha)](https://railway.com/deploy/bluesky-pds-atproto-spaces-alpha) — "The Atproto Spaces Alpha" version of Bluesky PDS.

Open this page in a browser: https://railway.com/deploy/writefreely-blogs
