Files

8.4 KiB

markMyWords

A self-hostable Docker application for hosting and searching markdown files with optional password protection and encryption.

Features

  • 🚀 Self-hosted: Run entirely on your own infrastructure
  • 📦 Docker-ready: Simple Docker Compose setup
  • 🔍 Full-text Search: Search across all markdown files
  • 📄 Markdown Rendering: Beautiful HTML rendering with syntax highlighting
  • 🔐 Encryption: Optional password-based file encryption
  • 🛡️ Access Control: Password-protect individual files
  • ⚡ Simple Setup: Just add files to the content/ directory

Quick Start

1. Setup Directory

cd markmywords

# Create necessary directories
mkdir -p content config data

2. Add Markdown Files

Copy your markdown files to the content/ directory:

cp /path/to/your/markdown/files/* ./content/

Organize with subdirectories as needed:

content/
├── README.md
├── docs/
│   ├── guide.md
│   └── tutorial.md
└── blog/
    ├── post1.md
    └── post2.md

3. Run with Docker Compose

docker-compose up -d

The application will be available at http://localhost:5000

4. Access the Application

  • Main Page: http://localhost:5000

    • Browse all files organized by directory
    • Search across all markdown content
  • View File: Click on any markdown file to view as HTML

  • Encrypted Files: Files with .md.enc extension require password authentication

  • Search: Full-text search across all unencrypted files

5. (Optional) Encrypt Files

Use the management script to encrypt sensitive files:

# Encrypt a file with a password
# File is automatically encrypted AND password-protected
python manage_content.py encrypt content/secret.md "mypassword"

# In browser: User enters password → file is decrypted and displayed
# Same password used for both encryption and browser access

See ENCRYPTION.md for more details.

File Management

Adding Content

Simply add markdown files to ./content/ and they appear automatically:

echo "# New Document" > content/new-file.md

The search index updates automatically when the app starts.

Directory Structure

Files are organized hierarchically in the UI:

content/
├── index.md          → Shows as "index" in root
├── docs/
│   ├── guide.md      → Shows as "docs > guide"
│   └── images/       → Images in subdirectories
│       └── diagram.png
└── archive/
    └── old.md        → Shows as "archive > old"

Supported Formats

  • Markdown: .md, .markdown
  • Encrypted Markdown: .md.enc (password-protected, viewed in browser)
  • Images: .png, .jpg, .jpeg, .gif, .webp (referenced in markdown)
  • Relative Paths: Images referenced with relative paths work correctly

Configuration

Docker Compose Configuration

The docker-compose.yml file manages:

  • Port mapping (default 5000)
  • Volume mounts for content and data
  • Restart policies
  • Encryption settings

To modify settings, edit docker-compose.yml:

services:
  markmywords:
    ports:
      - "5000:5000"  # Change port here if needed
    volumes:
      - ./content:/content:rw       # Your markdown files
      - ./config:/config:rw         # Password/protection config
      - ./data:/data:rw             # Search index
    environment:
      ENCRYPTION_ENABLED: "true"    # Enable/disable encryption

Environment Variables

# Flask secret key (REQUIRED for production)
export FLASK_SECRET_KEY="your-secure-random-key-here"

# Admin password for API operations (optional)
export MARKMYWORDS_ADMIN_PASSWORD="admin-password"

# Enable/disable file encryption feature
export ENCRYPTION_ENABLED="true"

API Endpoints

  • GET / - Main page with file browser
  • GET /view/<filepath> - View markdown file as HTML
  • GET /image/<filepath> - Serve images from content
  • GET /api/search?q=<query> - Full-text search
  • GET /api/status - Application status
  • POST /api/auth/<filepath> - Authenticate for protected file
  • POST /api/protect/<filepath> - Protect/unprotect files (admin only)
ports:
  - "8080:5000"  # Change external port to 8080

Advanced Configuration

SSH Repositories

For private repositories using SSH:

  1. Mount your SSH key:
volumes:
  - ~/.ssh:/root/.ssh:ro
  - ./config:/config:ro
  - markmywords_data:/data
  1. Use SSH URL in configuration:
{
  "private-repo": {
    "url": "git@github.com:username/private-repo.git",
    "enabled": true,
    "schedule": "0 * * * *"
  }
}

Custom Port

Edit docker-compose.yml:

ports:
  - "3000:5000"

Persistent Data

The Docker volume markmywords_data stores:

  • Cloned repositories (/data/repos)
  • Search index (/data/search_index)

To backup data:

docker-compose exec markmywords tar czf - /data > markmywords_backup.tar.gz

API Reference

GET /

Main page with repository list and search interface

GET /view//

View a markdown file as HTML

Parameters:

  • repo: Repository name
  • path: Path to markdown file within the repository

Example: /view/my-wiki/docs/getting-started.md

GET /api/search

Search across all markdown files

Query Parameters:

  • q: Search query (minimum 2 characters)

Response:

{
  "results": [
    {
      "path": "repo-name/path/to/file.md",
      "title": "File Title"
    }
  ]
}

GET /api/status

Get application status and repository information

Response:

{
  "status": "running",
  "repositories": {
    "repo-name": {
      "cloned": true,
      "last_modified": "2024-01-15T10:30:00"
    }
  },
  "timestamp": "2024-01-15T11:00:00"
}

Troubleshooting

Repositories Not Updating

  1. Check configuration file syntax:
docker-compose exec markmywords cat /config/repositories.json
  1. View application logs:
docker-compose logs -f markmywords
  1. Verify git access:
docker-compose exec markmywords git clone <url> /tmp/test

Search Not Working

  1. Ensure markdown files are present:
docker-compose exec markmywords ls -la /data/repos/
  1. Check search index:
docker-compose exec markmywords ls -la /data/search_index/
  1. Rebuild search index by restarting:
docker-compose restart markmywords

Port Already in Use

Change the port in docker-compose.yml:

ports:
  - "5001:5000"

Then run:

docker-compose up -d

Permissions

  • Git operations require read access to repositories
  • For private repositories, ensure proper SSH key setup
  • Web service runs as root inside container (safe for self-hosted)

Security Considerations

  • Only use HTTPS git URLs or secure SSH keys
  • Mount SSH keys as read-only
  • Use firewall rules to restrict access
  • Consider running behind a reverse proxy (nginx)
  • No authentication built-in; add via reverse proxy if needed

Performance

  • Search uses Whoosh full-text index
  • Index built on startup and updated after each pull
  • Markdown rendering uses Python markdown library with extensions

Architecture

┌─────────────────────────────────┐
│        markMyWords              │
│  (Flask + APScheduler)          │
├─────────────────────────────────┤
│ Scheduled Git Pulls (cron)      │
│ Markdown → HTML Conversion      │
│ Full-text Search (Whoosh)       │
├─────────────────────────────────┤
│        Docker Volume            │
│ - Cloned Repositories           │
│ - Search Index                  │
└─────────────────────────────────┘

Development

Local Setup

# Create virtual environment
python -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Create config
mkdir -p config
cp config/repositories.json.example config/repositories.json

# Run locally
python app.py

Requirements

  • Python 3.11+
  • Flask 3.0+
  • APScheduler 3.10+
  • markdown 3.5+
  • Whoosh 2.7+

License

MIT License - See LICENSE file for details

Contributing

Contributions welcome! Please submit issues and pull requests.

Support

For issues, questions, or suggestions, please open an issue on GitHub.