Florian.Walther e215b1d3b6
Docker Release Build / push_to_registry (push) Successful in 54s
added footer and app_version
2026-05-02 16:04:54 +02:00
2026-05-01 18:46:12 +02:00
2026-05-02 16:04:54 +02:00
2026-05-02 15:44:48 +02:00
2026-05-02 15:44:48 +02:00
2026-05-02 16:04:54 +02:00

mdhost

A simple, single-binary Go web application for hosting and sharing markdown files.

Features

  • Create, view, edit, and delete markdown files via web interface
  • Stable file IDs - unique identifiers don't change when files are edited
  • Syntax highlighting for code blocks (bash, go, python, etc.)
  • Optional authentication - anonymous users can create files, registered users can claim them
  • Access control - edit/delete only your own files, public/private visibility toggle
  • Responsive UI - mobile-friendly CSS layout
  • Persistent storage - all data (users, sessions, file metadata) survives server restarts

Quick Start

Build

go build -o mdhost .

Run

./mdhost

The server will start on http://localhost:8080.

Usage

  1. List files: Visit / to see all public markdown files
  2. Add a file: Click "add" in the nav bar, enter title and content, submit
  3. View a file: Click any file name in the list
  4. Edit a file: Click the [edit] link next to a file, or visit /edit?id=<file-id>
  5. Delete a file: Click the [delete] button (only visible for files you own)

Authentication

Anonymous Use

You can create and edit files without an account. Files created anonymously are associated with your browser session (via cookie).

Register

Click "register" in the nav bar to create an account. After registering:

  • Your existing anonymous files are automatically claimed and linked to your account
  • You can edit/delete all files created in your session

Login/Logout

  • Click "login" to authenticate with existing credentials
  • Click "logout" to end your session

Claiming Files

Files created while anonymous are automatically claimed when you register or login from the same browser.

File Visibility

  • Public files: Appear in the public list, visible to all users
  • Private files: Only accessible via direct URL, don't appear in public list
  • Toggle visibility using the "Listed in public list" checkbox when editing

Configuration

The following variables can be modified at the top of main.go:

var (
    postsDir  = "./posts"      // Directory for markdown files
    dataDir   = "./data"       // Directory for persistent data (data.json)
    port      = ":8080"        // Server port
)

var ListFormat = "ul"  // List rendering: "ul" (bullet), "ol" (numbered), "plain"

Data Storage

  • Markdown files: Stored in ./posts/ directory
  • Metadata: Stored in ./data/data.json (users, sessions, file metadata)
  • All data persists across server restarts

ID Generation

File IDs are generated as the first 12 characters of a SHA1 hash:

SHA1(filename + creation_timestamp)[:12]

The creation timestamp is stored in the file's CreatedAt field and persists across restarts, ensuring stable IDs.

Security

  • Passwords are hashed using bcrypt
  • Sessions use HTTP-only cookies with 1-year expiry
  • File ownership is enforced (users can only edit/delete their own files)
  • Private files are hidden from public listings but accessible via direct URL

API Endpoints

Method Path Description
GET / List all public files
GET /home Homepage with README
GET /view/{id} View rendered markdown
GET /add Form to create new file
POST /create Create new file
GET /edit Select file to edit
GET /edit?id={id} Edit specific file
POST /update Save file edits
POST /delete Delete a file
GET/POST /register Create user account
GET/POST /login Authenticate
GET /logout Clear session
GET /claim Claim anonymous files (auto-handled in register)

Docker

A pre-built Docker image is available from gitea.scu.si/florian.walther/mdhost:latest.

Build the Image

docker build -t mdhost .

Run with Docker

The data and posts directories are designed to be bind-mounted from the host filesystem for persistence:

# Create host directories for persistent data
mkdir -p ~/mdhost-data ~/mdhost-posts

# Run the container with bind mounts
docker run -d \
  --name mdhost \
  -p 8080:8080 \
  -v ~/mdhost-posts:/posts \
  -v ~/mdhost-data:/data \
  mdhost

The application will be available at http://localhost:8080.

  • /posts - Markdown files are stored here (bind-mounted from host)
  • /data - Metadata (users, sessions, file metadata) is stored here as data.json (bind-mounted from host)

Docker Compose

Create a docker-compose.yml:

version: '3.8'
services:
  mdhost:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ./posts:/posts
      - ./data:/data
    restart: unless-stopped

Then run:

docker compose up -d

Dependencies

  • Go 1.26+
  • github.com/yuin/goldmark v1.8.2
  • github.com/yuin/goldmark-highlighting v0.0.0-20220208100518-594be1970594
  • github.com/alecthomas/chroma/v2 v2.24.1
  • golang.org/x/crypto/bcrypt v0.50.0

License

MIT License

S
Description
a webapp to host markdown files
Readme
182 KiB
Languages
Go 98.6%
Dockerfile 1.4%