# 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 ```bash cd markmywords # Create necessary directories mkdir -p content config data ``` ### 2. Add Markdown Files Copy your markdown files to the `content/` directory: ```bash 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 ```bash 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: ```bash # 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](ENCRYPTION.md) for more details. ## File Management ### Adding Content Simply add markdown files to `./content/` and they appear automatically: ```bash 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`: ```yaml 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 ```bash # 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/` - View markdown file as HTML - `GET /image/` - Serve images from content - `GET /api/search?q=` - Full-text search - `GET /api/status` - Application status - `POST /api/auth/` - Authenticate for protected file - `POST /api/protect/` - Protect/unprotect files (admin only) ```yaml ports: - "8080:5000" # Change external port to 8080 ``` ## Advanced Configuration ### SSH Repositories For private repositories using SSH: 1. Mount your SSH key: ```yaml volumes: - ~/.ssh:/root/.ssh:ro - ./config:/config:ro - markmywords_data:/data ``` 2. Use SSH URL in configuration: ```json { "private-repo": { "url": "git@github.com:username/private-repo.git", "enabled": true, "schedule": "0 * * * *" } } ``` ### Custom Port Edit `docker-compose.yml`: ```yaml ports: - "3000:5000" ``` ### Persistent Data The Docker volume `markmywords_data` stores: - Cloned repositories (`/data/repos`) - Search index (`/data/search_index`) To backup data: ```bash 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**: ```json { "results": [ { "path": "repo-name/path/to/file.md", "title": "File Title" } ] } ``` ### GET /api/status Get application status and repository information **Response**: ```json { "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: ```bash docker-compose exec markmywords cat /config/repositories.json ``` 2. View application logs: ```bash docker-compose logs -f markmywords ``` 3. Verify git access: ```bash docker-compose exec markmywords git clone /tmp/test ``` ### Search Not Working 1. Ensure markdown files are present: ```bash docker-compose exec markmywords ls -la /data/repos/ ``` 2. Check search index: ```bash docker-compose exec markmywords ls -la /data/search_index/ ``` 3. Rebuild search index by restarting: ```bash docker-compose restart markmywords ``` ### Port Already in Use Change the port in `docker-compose.yml`: ```yaml ports: - "5001:5000" ``` Then run: ```bash 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 ```bash # 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.