A deployable markdown editor that connects with your self hosted files and lets you edit in a beautiful interface

MarkEdit Setup Guide#

This guide will help you set up and deploy MarkEdit for production or development use.

Table of Contents#

Prerequisites#

For Docker Deployment#

  • Docker 20.x or higher
  • Docker Compose 2.x or higher
  • GitHub account with OAuth app

For Local Development#

  • Go 1.24 or higher
  • Bun 1.x or higher (for frontend)
  • Git
  • GitHub account with OAuth app

GitHub OAuth Setup#

MarkEdit uses GitHub OAuth for authentication. You need to create a GitHub OAuth application:

1. Create OAuth Application#

  1. Go to GitHub Developer Settings
  2. Click "New OAuth App"
  3. Fill in the application details:
    • Application name: MarkEdit (or your preferred name)
    • Homepage URL: http://localhost:3000 (for development)
    • Authorization callback URL: http://localhost:8080/auth/github/callback
  4. Click "Register application"

2. Get Credentials#

After registration, you'll see:

  • Client ID - Copy this value
  • Client Secret - Click "Generate a new client secret" and copy the value

⚠️ Important: Keep your Client Secret secure! Never commit it to version control.

3. Production URLs#

For production deployment, create a separate OAuth app with production URLs:

  • Homepage URL: https://yourdomain.com
  • Authorization callback URL: https://yourdomain.com/auth/github/callback

Development Setup#

1. Clone Repository#

git clone https://tangled.org/usaa.ma/markedit
cd markedit

2. Configure Environment Variables#

Backend Configuration#

Create backend/.env:

cd backend
cp .env.example .env

Edit backend/.env:

# GitHub OAuth
GITHUB_CLIENT_ID=your_github_oauth_client_id_here
GITHUB_CLIENT_SECRET=your_github_oauth_client_secret_here

# Session Security
SESSION_SECRET=generate-a-random-32-character-string-here

# Database
DATABASE_PATH=./data/markedit.db

# Git Cache
GIT_CACHE_DIR=./data/repos

# CORS (adjust based on your frontend URL)
CORS_ALLOWED_ORIGINS=http://localhost:4321,http://localhost:3000

# Server
PORT=8080

Generate SESSION_SECRET:

# On macOS/Linux:
openssl rand -base64 32

# Or use Go:
go run -c 'package main; import ("crypto/rand"; "encoding/base64"; "fmt"); func main() { b := make([]byte, 32); rand.Read(b); fmt.Println(base64.StdEncoding.EncodeToString(b)) }'

Frontend Configuration#

Create frontend/.env:

cd ../frontend
echo "PUBLIC_API_URL=http://localhost:8080" > .env

3. Run Backend#

cd backend

# Install dependencies
go mod download

# Create data directory
mkdir -p data

# Run server
go run cmd/server/main.go

Backend will start on http://localhost:8080

4. Run Frontend#

In a new terminal:

cd frontend

# Install dependencies
bun install

# Start dev server
bun run dev

Frontend will start on http://localhost:4321

5. Access Application#

  1. Open browser to http://localhost:4321
  2. Click "Sign in with GitHub"
  3. Authorize the application
  4. Start editing!

Docker Deployment#

Docker deployment is the recommended method for production.

1. Configure Environment#

Create .env in the project root:

cp .env.example .env

Edit .env:

# GitHub OAuth (use production OAuth app)
GITHUB_CLIENT_ID=your_production_github_oauth_client_id
GITHUB_CLIENT_SECRET=your_production_github_oauth_client_secret

# Session Security
SESSION_SECRET=generate-a-secure-random-32-character-string

# Database
DATABASE_PATH=/app/data/markedit.db

# Git Cache
GIT_CACHE_DIR=/app/data/repos

# CORS (adjust for your domain)
CORS_ALLOWED_ORIGINS=https://yourdomain.com,http://localhost:3000

# Server
PORT=8080

2. Build Images#

make build

Or manually:

docker-compose build

3. Start Services#

make up

Or manually:

docker-compose up -d

4. Verify Deployment#

Check if services are running:

make logs

Or:

docker-compose logs -f

Access the application at http://localhost:3000

5. Stop Services#

make down

Production Deployment#

Option 1: Docker on VPS#

1. Server Setup#

On your VPS (Ubuntu/Debian):

# Update system
sudo apt update && sudo apt upgrade -y

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Install Docker Compose
sudo apt install docker-compose-plugin

# Create app directory
mkdir -p ~/markedit
cd ~/markedit

2. Deploy Application#

# Clone repository
git clone https://tangled.org/usaa.ma/markedit

# Configure environment
cp .env.example .env
nano .env  # Edit with production values

# Build and start
docker-compose up -d

# Check logs
docker-compose logs -f

3. Setup Reverse Proxy (nginx)#

Install nginx:

sudo apt install nginx certbot python3-certbot-nginx

Create nginx config /etc/nginx/sites-available/markedit:

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable site and get SSL:

sudo ln -s /etc/nginx/sites-available/markedit /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d yourdomain.com

Option 2: Docker on Cloud Platform#

AWS ECS / Google Cloud Run / Azure Container Instances#

  1. Build and push images to container registry:
# Tag images
docker tag markedit-backend:latest your-registry/markedit-backend:latest
docker tag markedit-frontend:latest your-registry/markedit-frontend:latest

# Push images
docker push your-registry/markedit-backend:latest
docker push your-registry/markedit-frontend:latest
  1. Deploy using platform-specific tools
  2. Configure environment variables in platform dashboard
  3. Set up load balancer and SSL certificate

Option 3: Manual Deployment#

Backend#

# Build binary
cd backend
go build -o markedit-server cmd/server/main.go

# Run with systemd
sudo cp markedit-server /usr/local/bin/
sudo nano /etc/systemd/system/markedit.service

Create systemd service:

[Unit]
Description=MarkEdit Server
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/markedit
EnvironmentFile=/var/www/markedit/.env
ExecStart=/usr/local/bin/markedit-server
Restart=always

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable markedit
sudo systemctl start markedit

Frontend#

cd frontend
bun install
bun run build

# Serve with nginx
sudo cp -r dist/* /var/www/html/

Configuration Reference#

Backend Environment Variables#

Variable Required Default Description
GITHUB_CLIENT_ID Yes - GitHub OAuth client ID
GITHUB_CLIENT_SECRET Yes - GitHub OAuth client secret
SESSION_SECRET Yes - 32+ character random string for session encryption
DATABASE_PATH No ./data/markedit.db Path to SQLite database file
GIT_CACHE_DIR No ./data/repos Directory for git repository cache
CORS_ALLOWED_ORIGINS No http://localhost:4321 Comma-separated allowed origins
PORT No 8080 Server port

Frontend Environment Variables#

Variable Required Default Description
PUBLIC_API_URL Yes - Backend API URL (e.g., http://localhost:8080)

Docker Compose Ports#

Service Internal Port External Port Description
Backend 8080 8080 API server
Frontend 80 3000 Web interface

Troubleshooting#

GitHub OAuth Issues#

Problem: "OAuth callback error" or "Invalid client"

Solution:

  1. Verify GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET are correct
  2. Check callback URL in GitHub OAuth app matches your backend URL
  3. Ensure callback URL format: http://localhost:8080/auth/github/callback

Database Issues#

Problem: "Unable to open database"

Solution:

  1. Ensure data directory exists: mkdir -p data
  2. Check file permissions: chmod 755 data
  3. Verify DATABASE_PATH environment variable

Git Operations Fail#

Problem: "Failed to clone repository" or "Authentication failed"

Solution:

  1. User must have granted repository access during OAuth
  2. Check GitHub token has correct scopes (repo)
  3. Verify GIT_CACHE_DIR is writable

CORS Issues#

Problem: "CORS policy: No 'Access-Control-Allow-Origin' header"

Solution:

  1. Add frontend URL to CORS_ALLOWED_ORIGINS
  2. Format: http://localhost:4321,https://yourdomain.com
  3. Restart backend server

Docker Build Fails#

Problem: Build errors or dependency issues

Solution:

# Clean Docker cache
docker-compose down -v
docker system prune -a

# Rebuild from scratch
make build
make up

Frontend Can't Connect to Backend#

Problem: "Network error" or "Failed to fetch"

Solution:

  1. Verify backend is running: curl http://localhost:8080/health
  2. Check PUBLIC_API_URL in frontend .env
  3. Ensure CORS is configured correctly
  4. Check browser console for specific errors

Port Already in Use#

Problem: "Address already in use"

Solution:

# Find process using port
lsof -i :8080  # or :3000

# Kill process
kill -9 <PID>

# Or change port in configuration

Security Best Practices#

  1. Never commit secrets: Keep .env files out of version control
  2. Use strong SESSION_SECRET: Minimum 32 random characters
  3. Enable HTTPS: Use SSL certificates in production
  4. Restrict CORS: Only allow trusted domains
  5. Regular updates: Keep dependencies up to date
  6. Backup database: Regularly backup markedit.db
  7. Monitor logs: Check for unauthorized access attempts

Backup and Restore#

Backup#

# Database
cp data/markedit.db backups/markedit-$(date +%Y%m%d).db

# Git cache (optional)
tar -czf backups/repos-$(date +%Y%m%d).tar.gz data/repos/

Restore#

# Database
cp backups/markedit-20240101.db data/markedit.db

# Restart services
docker-compose restart

Support#

Next Steps#

After setup:

  1. Sign in with GitHub
  2. Configure your first repository
  3. Start editing markdown files
  4. Create your first pull request

Happy editing! 🎉