---
title: "Deploy Hexo"
description: "Self-hosted Hexo blog with editor, comments, and S3 storage"
category: "Blogs"
url: https://railway.com/deploy/hexo
---

# Deploy Hexo

Self-hosted Hexo blog with editor, comments, and S3 storage

**[Deploy Hexo on Railway](https://railway.com/template/hexo)**

- **Creator:** INAPP
- **Category:** Blogs

## Template content

### storage

- **Source:** https://github.com/INAPP-Mobile/hexo
- **Public domain:** Yes

### comments

- **Source:** https://github.com/INAPP-Mobile/hexo
- **Public domain:** Yes

### hexo

- **Source:** https://github.com/INAPP-Mobile/hexo
- **Public domain:** Yes

## Documentation

# Deploy and Host

[![Deploy on Railway](https://railway.app/button.svg)](https://railway.com/deploy/hexo)

![Hexo Blog Platform](https://raw.githubusercontent.com/INAPP-Mobile/hexo/main/template-icon.svg)

Hexo Blog Platform is a complete self-hosted blogging stack on Railway: a fast static blog with a browser-based editor and web terminal, plus a separate self-hosted comment system (Artalk) and S3-compatible object storage (MinIO) — **three services, three public URLs**, all provisioned with one click.

## About Hosting

The template deploys three independent services, each built from its own Dockerfile and each with its own persistent volume at `/data`:

- **hexo** — nginx + Hexo 8 + hexo-admin editor + ttyd web terminal (supervisord-managed), `PORT=80`
- **comments** — Artalk 2.x comment system (SQLite by default; PostgreSQL/MySQL optional), `PORT=8080`
- **storage** — MinIO S3-compatible object storage, `PORT=9000`

Railway provides compute, TLS at the edge, public URLs, and volumes. New posts auto-regenerate the static site within ~60 seconds. Images pasted into the editor upload straight to MinIO (public-read `blog-images` bucket), so they survive redeploys.

## Why Deploy

- **All-in-one blogging platform** — blog, browser editor, web terminal, comments, and S3 storage in one deploy
- **Self-hosted comments** — Artalk with SQLite on a persistent volume; no third-party comment service
- **S3-backed image upload** — editor images go to your own MinIO bucket, not the local disk
- **Web terminal** — ttyd shell for `hexo`, `git`, and `npm` maintenance, protected by HTTP Basic Auth
- **Persistent volumes** — content, generated site, comment DB, and MinIO data survive restarts
- **Auto-generated credentials** — every deploy form generates admin, moderator, and MinIO passwords for you

## Common Use Cases

- **Personal blog** — write Markdown posts from the browser at `/admin/`, publish with one click
- **Multi-author site** — share the editor credentials; moderate comments from the `/sidebar/` dashboard
- **Self-hosted comments** — replace Disqus/utterances with your own Artalk instance wired to any Hexo/static site
- **Private image/media storage** — use the MinIO service as an S3 endpoint for any app (`mc`, `rclone`, AWS SDKs)

## Dependencies for Hexo

No external accounts, API keys, or client tools are required. Everything is provisioned by Railway on deploy.

### Deployment Dependencies

Railway builds each service from its Dockerfiles (Dockerfile, `comments/Dockerfile`, `storage/Dockerfile`). Three volumes are mounted at `/data`. The deploy form generates all credentials via `${{secret(16)}}` placeholders; `ARTALK_SITE_URL` and `MINIO_ENDPOINT` are auto-derived from the services' public domains via `${{comments.RAILWAY_PUBLIC_DOMAIN}}` / `${{storage.RAILWAY_PUBLIC_DOMAIN}}`.

## Services &amp; URLs

| Service | Purpose | Default Path | Example URL |
|---------|---------|--------------|-------------|
| **hexo** | Blog + editor + terminal | `/`, `/admin/`, `/terminal/` | `https://hexo-production-xxxx.up.railway.app` |
| **comments** | Artalk comments (widget + API + moderation) | `/` (API), `/sidebar/` (dashboard) | `https://comments-production-xxxx.up.railway.app` |
| **storage** | MinIO S3 object storage | `/` (path-style API: `/bucket/key`) | `https://storage-production-xxxx.up.railway.app` |

## Features

- **Hexo static site** — Markdown-powered blog (Hexo 8) served by nginx. New posts auto-regenerate within ~60 seconds.
- **hexo-admin editor** — Write, edit and publish posts from the browser at `/admin/`. Password-protected (auto-generated credentials on one-click deploy).
- **Web terminal** — ttyd shell at `/terminal/` for `hexo`, `git`, `npm` and any maintenance task. Protected with the same admin credentials (HTTP Basic Auth).
- **Artalk comments** — Self-hosted comment system with SQLite storage on a persistent volume (PostgreSQL/MySQL optional via `ARTALK_DB_TYPE` + `DATABASE_URL`). Moderation dashboard at `/sidebar/` on the comments service URL (Artalk 2.x moved the console there).
- **MinIO S3 storage** — S3-compatible object storage API at the storage service URL root (path-style: `/bucket/key`). Perfect for images, media, backups. The web console binds an internal port and is not publicly exposed — use `mc`, `rclone` or any S3 SDK.
- **S3-backed image upload** — Images pasted into the hexo-admin editor are uploaded straight to MinIO (auto-created `blog-images` bucket, public-read policy) instead of the local disk, so they survive redeploys and are served from the storage service URL.
- **Persistent volumes** — Each service gets its own `/data` volume keeping content, generated site, comments DB, and MinIO data across restarts.
- **Client-side search** — `/search.xml` generated by hexo-generator-searchdb.

## Prerequisites

- A Railway account (free tier works).
- Nothing else — the deploy form generates all credentials for you.

## Quick Start

1. Click **Deploy to Railway** (button above).
2. Railway generates all passwords automatically (hexo admin, Artalk moderator, MinIO root).
3. After deploy, note the three service URLs from Railway's dashboard:
   - **Blog/Editor/Terminal**: hexo service domain
   - **Comments**: comments service domain → `/sidebar/` for moderation
   - **MinIO**: storage service domain → S3 API endpoint
4. Log in and start writing!

### Credentials (auto-generated, read from each service's **Variables** tab)

| Service | Username | Variable |
|---------|----------|----------|
| hexo (editor + terminal) | `ADMIN_USERNAME` (default `admin`) | `ADMIN_PASSWORD` |
| comments (Artalk) | `ARTALK_ADMIN_EMAIL` | `ARTALK_ADMIN_PASSWORD` |
| storage (MinIO) | `MINIO_ROOT_USER` (default `minioadmin`) | `MINIO_ROOT_PASSWORD` |

## Environment

All configuration is via environment variables (see `.env.example`). Key variables:

- `TZ` — Timezone for all services (default `UTC`)
- `ADMIN_USERNAME` / `ADMIN_PASSWORD` — hexo-admin editor and terminal login
- `ARTALK_SITE_NAME` — Display name in comment widget
- `ARTALK_DB_TYPE` — `sqlite` (default), `pgsql`, `mysql`, `mssql`
- `ARTALK_TRUSTED_DOMAINS` — CORS origins for comment API (auto-includes hexo domain)
- `ARTALK_LOCALE` / `ARTALK_TIMEZONE` — UI language &amp; timezone
- `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD` — S3 root credentials
- `MINIO_ENDPOINT` / `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` / `MINIO_BUCKET` — S3-backed editor image upload (auto-derived from the storage service)

## Writing Posts

1. Open your hexo service URL → `/admin/`
2. Log in with `ADMIN_USERNAME` / `ADMIN_PASSWORD`
3. Create a new post → it appears on the blog within ~60 seconds (auto-regenerate)
4. Or use the web terminal (`/terminal/`) for `npx hexo new "My Post"` and `npx hexo generate`

## Comment Moderation

Open the **comments** service URL → `/sidebar/` → log in with `ARTALK_ADMIN_EMAIL` / `ARTALK_ADMIN_PASSWORD`

## Object Storage (MinIO)

- **S3 API**: `https:///` (path-style access: `https:////`)
- Credentials: `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD`
- Compatible with `mc`, `rclone`, AWS SDKs, etc.
- The web console is bound to an internal port (not publicly exposed) — manage buckets via `mc` / SDKs.

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│  Railway Project                                            │
├─────────────────┬─────────────────────┬────────────────────┤
│   (repo root)   │    comments/        │    storage/        │
│  nginx+hexo+    │  (artalk/artalk-go  │  (minio/minio +    │
│   ttyd          │   + entrypoint)     │   entrypoint)      │
│  PORT=80        │  PORT=8080          │  PORT=9000         │
│  /data volume   │  /data volume       │  /data volume      │
└────────┬────────┴─────────┬────────────┴────────┬──────────┘
         │                  │                     │
         ▼                  ▼                     ▼
   hexo service       comments service      storage service
   (public domain)    (public domain)       (public domain)
```

Each service is independent, has its own volume, and scales separately. The blog's comment widget talks to the comments service over HTTPS via `ARTALK_SITE_URL` (auto-derived from the comments service's public domain).

## Local Development

```bash
# Build and test hexo service locally (requires podman)
podman build -t hexo-test .
podman run -p 8080:80 -v $PWD/test-data:/data hexo-test
# Open http://localhost:8080/
```

## Deploy

This is a three-service template:

- **hexo** — built from the repo root `Dockerfile` (nginx + hexo + hexo-admin + ttyd via supervisord)
- **comments** — built from `comments/Dockerfile` (official Artalk image + config entrypoint)
- **storage** — built from `storage/Dockerfile` (official MinIO image + entrypoint)

All three get a persistent volume mounted at `/data`. Click the Deploy button, and Railway provisions everything.

## Upstream Sources

- Hexo: https://github.com/hexojs/hexo
- hexo-admin: https://github.com/jaredly/hexo-admin
- Artalk: https://github.com/ArtalkJS/Artalk
- MinIO: https://github.com/minio/minio
- ttyd: https://github.com/tsl0922/ttyd


## Similar templates

- [Pixelfed](https://railway.com/deploy/OZSdEw) — Explore + Share beautiful photos and videos on the Fediverse
- [NodeBB](https://railway.com/deploy/nodebb) — Node.js based forum software built for the modern web
- [WordPress + MySQL](https://railway.com/deploy/yG1Jw8) — Zero Config | One click | WordPress | Docker | MySQL

Open this page in a browser: https://railway.com/deploy/hexo
