# 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 ```bash go build -o mdhost . ``` ### Run ```bash ./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=` 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`: ```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 ```bash docker build -t mdhost . ``` ### Run with Docker The `data` and `posts` directories are designed to be bind-mounted from the host filesystem for persistence: ```bash # 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 \ gitea.scu.si/florian.walther/mdhost:latest ``` 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`: ```yaml version: '3.8' services: mdhost: image: gitea.scu.si/florian.walther/mdhost:latest # build: . ports: - "8080:8080" volumes: - ./posts:/posts - ./data:/data restart: unless-stopped ``` Then run: ```bash 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