SHA256
390 lines
8.4 KiB
Markdown
390 lines
8.4 KiB
Markdown
# 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/<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)
|
|
|
|
```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/<repo>/<path>
|
|
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 <url> /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.
|