Skip to content

Deploying DOCAT

DOCAT is a lightweight, self-hosted documentation hosting platform designed to simplify the process of managing and serving multiple versions of project documentation. Built with simplicity and efficiency in mind, DOCAT allows development teams to upload, organize, and serve documentation for different versions of their software projects through a clean, intuitive web interface.

Unlike complex documentation platforms that require extensive configuration and maintenance, DOCAT focuses on doing one thing exceptionally well: hosting versioned documentation. The platform automatically generates a version selector, provides a simple upload mechanism via its API, and serves documentation with minimal overhead. Whether you’re documenting internal tools, open-source projects, or commercial software, DOCAT provides a straightforward solution that integrates seamlessly into CI/CD pipelines and development workflows.

Why Deploy DOCAT on Klutch.sh?

Klutch.sh provides an ideal platform for hosting DOCAT with several key advantages:

  • Simple Docker Deployment: Deploy your Dockerfile and Klutch.sh automatically handles containerization and orchestration
  • Persistent Storage: Attach volumes to store documentation across deployments, ensuring your docs are never lost
  • Automatic HTTPS: All deployments come with automatic SSL certificates for secure documentation access
  • Cost-Effective Hosting: DOCAT’s lightweight design means minimal resource usage and lower hosting costs
  • Zero Maintenance: No need to manage servers, updates are as simple as rebuilding your container
  • Instant Scaling: Adjust resources as your documentation library grows
  • CI/CD Integration: Easy integration with GitHub Actions or GitLab CI for automated documentation deployment

Prerequisites

Before deploying DOCAT, ensure you have:

  • A Klutch.sh account (sign up at klutch.sh)
  • Git installed locally
  • Basic familiarity with Docker
  • Documentation to host (HTML, static sites from Sphinx, MkDocs, JSDoc, etc.)
  • Understanding of RESTful APIs for documentation uploads
  • Node.js and npm (for local testing with DOCAT CLI)

Understanding DOCAT’s Architecture

DOCAT uses a straightforward architecture optimized for serving static documentation:

Core Components

Nginx Web Server: DOCAT uses Nginx as its primary web server to serve static documentation files. Nginx handles HTTP requests, serves documentation content, and manages routing between different project versions.

Backend API: A lightweight Python/Flask API manages documentation uploads, version management, and project organization. The API provides endpoints for:

  • Uploading new documentation versions
  • Listing available projects and versions
  • Managing documentation metadata
  • Deleting old versions

File System Storage: Documentation is stored in a structured directory hierarchy on the file system:

/doc
├── project-name/
│ ├── 1.0.0/
│ │ └── index.html
│ ├── 1.1.0/
│ │ └── index.html
│ └── latest/
│ └── index.html

Frontend Interface: A simple, responsive web interface allows users to:

  • Browse available projects
  • Select documentation versions
  • Navigate through documentation
  • Search across versions (if enabled)

Request Flow

  1. User accesses DOCAT via web browser
  2. Nginx serves the frontend application
  3. User selects a project and version
  4. Nginx serves static documentation files from the file system
  5. Version selector automatically updates based on available versions
  6. API handles upload requests from CI/CD pipelines or manual uploads

Version Management

DOCAT manages documentation versions through:

  • Semantic Versioning: Supports standard semantic version formats (1.0.0, 2.1.3, etc.)
  • Branch Names: Can host documentation for feature branches
  • Tags: Support for custom tags like “stable”, “latest”, “beta”
  • Automatic Indexing: Automatically generates project and version listings

Upload Mechanism

Documentation can be uploaded via:

  • HTTP API: POST requests with documentation archives (zip/tar.gz)
  • DOCAT CLI: Command-line tool for easy uploads
  • CI/CD Integration: Direct integration from build pipelines
  • Manual Upload: Via curl or other HTTP clients

Installation and Setup

Step 1: Create the Dockerfile

Create a Dockerfile in your project root. We’ll use the official DOCAT image as a base:

FROM docat/docat:latest
# Install additional dependencies if needed
RUN apt-get update && apt-get install -y \
curl \
vim \
&& rm -rf /var/lib/apt/lists/*
# Create upload token file (optional, for secure uploads)
RUN mkdir -p /app/docat
COPY upload_tokens.json /app/docat/upload_tokens.json
# Set proper permissions
RUN chown -R nginx:nginx /var/www/html /doc
# Expose port
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# Use default CMD from base image

Alternatively, build from scratch for more control:

FROM python:3.11-alpine
# Install system dependencies
RUN apk add --no-cache \
nginx \
supervisor \
curl
# Create app directory
WORKDIR /app
# Install DOCAT
RUN pip install --no-cache-dir docat
# Copy Nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf
# Copy supervisor configuration
COPY supervisord.conf /etc/supervisord.conf
# Create necessary directories
RUN mkdir -p /doc /var/log/docat /var/log/nginx /run/nginx \
&& chown -R nginx:nginx /doc /var/log/docat
# Expose port
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# Start supervisor
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

Step 2: Create Upload Tokens Configuration

Create upload_tokens.json to secure documentation uploads:

{
"tokens": [
{
"name": "ci-token",
"token": "your-secure-token-here-change-in-production",
"projects": ["*"]
},
{
"name": "project-specific-token",
"token": "another-secure-token",
"projects": ["my-project", "another-project"]
}
]
}

Security Note: Generate strong tokens using:

Terminal window
openssl rand -base64 32

Step 3: Create Nginx Configuration

Create nginx.conf (if building from scratch):

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 100M;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss
application/rss+xml application/atom+xml image/svg+xml
text/x-js text/x-component text/x-cross-domain-policy;
server {
listen 80;
server_name localhost;
# API endpoints
location /api/ {
proxy_pass http://localhost:5000/;
proxy_set_header Host $host;
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;
}
# Documentation files
location /doc/ {
alias /doc/;
autoindex off;
try_files $uri $uri/ =404;
}
# Frontend application
location / {
root /var/www/html;
try_files $uri $uri/ /index.html;
}
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
}

Step 4: Create Supervisor Configuration

Create supervisord.conf (if building from scratch):

[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
[program:docat]
command=python -m docat.app
directory=/app
autostart=true
autorestart=true
stderr_logfile=/var/log/docat/docat.err.log
stdout_logfile=/var/log/docat/docat.out.log
[program:nginx]
command=nginx -g "daemon off;"
autostart=true
autorestart=true
stderr_logfile=/var/log/nginx/error.log
stdout_logfile=/var/log/nginx/access.log

Step 5: Create Environment Configuration

Create .env file for local development:

Terminal window
# DOCAT Configuration
DOCAT_UPLOAD_TOKEN=your-secure-token-here
DOCAT_SERVE_PORT=80
DOCAT_DOC_PATH=/doc
# Storage
DOC_STORAGE_PATH=/doc
# API Configuration
API_PORT=5000
API_HOST=0.0.0.0
# Feature flags
ENABLE_SEARCH=true
ENABLE_VERSIONS=true

Step 6: Create Docker Compose for Local Development

Create docker-compose.yml for local testing:

version: '3.8'
services:
docat:
build: .
ports:
- "8080:80"
volumes:
- docat-docs:/doc
- ./upload_tokens.json:/app/docat/upload_tokens.json:ro
environment:
- DOCAT_UPLOAD_TOKEN=${DOCAT_UPLOAD_TOKEN:-change-me}
restart: unless-stopped
volumes:
docat-docs:

Step 7: Initialize Git Repository

Terminal window
git init
git add Dockerfile nginx.conf supervisord.conf upload_tokens.json docker-compose.yml .env
git commit -m "Initial DOCAT deployment configuration"

Step 8: Test Locally

Before deploying to Klutch.sh, test your configuration locally:

Terminal window
# Build and start the container
docker-compose up -d
# Check logs
docker-compose logs -f
# Access DOCAT at http://localhost:8080
# Test upload (requires documentation to upload)
curl -X POST http://localhost:8080/api/project/test-project/1.0.0 \
-H "Docat-Api-Key: your-secure-token-here" \
-F "file=@docs.tar.gz"

Deploying to Klutch.sh

Step 1: Push to GitHub

Create a new repository on GitHub and push your code:

Terminal window
git remote add origin https://github.com/yourusername/docat-klutch.git
git branch -M master
git push -u origin master

Step 2: Connect Repository to Klutch.sh

  1. Navigate to klutch.sh/app
  2. Click "New Project" and select "Import from GitHub"
  3. Authorize Klutch.sh to access your GitHub repositories
  4. Select your DOCAT repository from the list
  5. Klutch.sh will automatically detect the Dockerfile in your repository

Step 3: Configure Traffic Settings

  1. In the project settings, select **HTTP** as the traffic type
  2. Set the internal port to **80**
  3. Klutch.sh will automatically provision an HTTPS endpoint for your application

Step 4: Add Persistent Storage

DOCAT requires persistent storage for documentation files:

  1. In your project settings, navigate to the "Storage" section
  2. Add a volume with mount path: `/doc` and size: `20GB` (adjust based on documentation size)

Storage recommendations:

  • Small projects (1-5 projects): 10GB
  • Medium projects (5-20 projects): 20GB - 50GB
  • Large organizations (20+ projects): 50GB - 200GB+

Step 5: Configure Environment Variables

Add the following environment variables in your Klutch.sh dashboard:

  • DOCAT_UPLOAD_TOKEN: Your secure upload token (generate with openssl rand -base64 32)
  • DOCAT_SERVE_PORT: 80
  • DOCAT_DOC_PATH: /doc

Optional variables:

  • ENABLE_SEARCH: true (if search functionality is needed)
  • API_PORT: 5000

Step 6: Deploy

  1. Review your configuration settings
  2. Click "Deploy" to start the deployment process
  3. Klutch.sh will build your Docker image and deploy the container
  4. Monitor the build logs for any errors
  5. Once deployed, your DOCAT instance will be available at `your-app.klutch.sh`

Getting Started with DOCAT

Initial Setup

After your first deployment, access your DOCAT instance:

  1. Navigate to Your Instance: Visit https://your-app.klutch.sh

  2. Verify Installation: You should see the DOCAT interface with no projects listed initially

  3. Prepare Upload Token: Keep your DOCAT_UPLOAD_TOKEN handy for uploading documentation

Preparing Documentation

DOCAT accepts documentation in various formats. Here’s how to prepare common documentation types:

Sphinx Documentation

Terminal window
# Build Sphinx documentation
cd docs/
make html
# Create archive
cd _build/html
tar -czf ../../sphinx-docs.tar.gz .

MkDocs Documentation

Terminal window
# Build MkDocs site
mkdocs build
# Create archive
cd site/
tar -czf ../mkdocs-docs.tar.gz .

JSDoc Documentation

Terminal window
# Generate JSDoc
jsdoc -c jsdoc.json -r src/ -d docs/
# Create archive
cd docs/
tar -czf ../jsdoc-docs.tar.gz .

Static HTML Documentation

Terminal window
# Any static HTML site
cd your-docs/
tar -czf ../docs.tar.gz .

Uploading Documentation

Method 1: Using curl

Upload documentation directly via curl:

Terminal window
# Upload version 1.0.0 of my-project
curl -X POST https://your-app.klutch.sh/api/project/my-project/1.0.0 \
-H "Docat-Api-Key: your-secure-token-here" \
-F "file=@docs.tar.gz"
# Upload with branch name
curl -X POST https://your-app.klutch.sh/api/project/my-project/feature-branch \
-H "Docat-Api-Key: your-secure-token-here" \
-F "file=@docs.tar.gz"
# Upload as "latest"
curl -X POST https://your-app.klutch.sh/api/project/my-project/latest \
-H "Docat-Api-Key: your-secure-token-here" \
-F "file=@docs.tar.gz"

Response on success:

{
"message": "Documentation uploaded successfully",
"project": "my-project",
"version": "1.0.0"
}

Method 2: Using DOCAT CLI

Install the DOCAT CLI tool:

Terminal window
npm install -g docat-cli

Upload documentation:

Terminal window
# Configure DOCAT CLI
export DOCAT_URL=https://your-app.klutch.sh
export DOCAT_API_KEY=your-secure-token-here
# Upload documentation
docat push --project my-project --version 1.0.0 ./docs/
# Upload from build directory
cd build/html && docat push --project my-project --version 2.0.0 .

Method 3: CI/CD Integration

GitHub Actions Example:

.github/workflows/deploy-docs.yml
name: Deploy Documentation
on:
push:
tags:
- 'v*'
jobs:
deploy-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install sphinx sphinx-rtd-theme
- name: Build documentation
run: |
cd docs
make html
- name: Create archive
run: |
cd docs/_build/html
tar -czf ../../../docs.tar.gz .
- name: Extract version from tag
id: get_version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Upload to DOCAT
env:
DOCAT_URL: ${{ secrets.DOCAT_URL }}
DOCAT_API_KEY: ${{ secrets.DOCAT_API_KEY }}
run: |
curl -X POST $DOCAT_URL/api/project/my-project/${{ steps.get_version.outputs.VERSION }} \
-H "Docat-Api-Key: $DOCAT_API_KEY" \
-F "file=@docs.tar.gz"

GitLab CI Example:

.gitlab-ci.yml
deploy-docs:
stage: deploy
image: python:3.11
script:
- pip install sphinx sphinx-rtd-theme
- cd docs && make html
- cd _build/html && tar -czf ../../../docs.tar.gz .
- cd ../../..
- |
curl -X POST $DOCAT_URL/api/project/my-project/$CI_COMMIT_TAG \
-H "Docat-Api-Key: $DOCAT_API_KEY" \
-F "file=@docs.tar.gz"
only:
- tags
variables:
DOCAT_URL: "https://your-app.klutch.sh"

Accessing Documentation

Once uploaded, access your documentation:

  1. Navigate to DOCAT: Visit https://your-app.klutch.sh
  2. Select Project: Click on your project name
  3. Choose Version: Select the version from the dropdown
  4. Browse Documentation: Navigate through your docs

Direct URL format:

https://your-app.klutch.sh/doc/project-name/version/
https://your-app.klutch.sh/doc/my-project/1.0.0/
https://your-app.klutch.sh/doc/my-project/latest/

Managing Documentation Versions

List All Projects

Terminal window
curl https://your-app.klutch.sh/api/projects

Response:

{
"projects": [
{
"name": "my-project",
"versions": ["1.0.0", "1.1.0", "2.0.0", "latest"]
},
{
"name": "another-project",
"versions": ["1.0.0"]
}
]
}

List Versions for a Project

Terminal window
curl https://your-app.klutch.sh/api/project/my-project

Response:

{
"project": "my-project",
"versions": ["1.0.0", "1.1.0", "2.0.0", "latest"]
}

Delete a Version

Terminal window
curl -X DELETE https://your-app.klutch.sh/api/project/my-project/1.0.0 \
-H "Docat-Api-Key: your-secure-token-here"

Delete an Entire Project

Terminal window
curl -X DELETE https://your-app.klutch.sh/api/project/my-project \
-H "Docat-Api-Key: your-secure-token-here"

Production Best Practices

Security Hardening

  1. Strong Upload Tokens: Generate cryptographically secure tokens:
Terminal window
# Generate a strong token
openssl rand -base64 32
# Update environment variable in Klutch.sh
DOCAT_UPLOAD_TOKEN=<generated-token>
  1. Token Rotation: Regularly rotate upload tokens:
{
"tokens": [
{
"name": "ci-token-2024",
"token": "new-secure-token",
"projects": ["*"],
"created": "2024-01-01"
}
]
}
  1. Project-Specific Tokens: Use different tokens for different projects:
{
"tokens": [
{
"name": "frontend-team",
"token": "token-for-frontend-projects",
"projects": ["web-app", "mobile-app", "admin-panel"]
},
{
"name": "backend-team",
"token": "token-for-backend-projects",
"projects": ["api-server", "worker-service"]
}
]
}
  1. HTTPS Only: Ensure all connections use HTTPS (automatic with Klutch.sh)

  2. Security Headers: Add additional security headers in Nginx:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

Backup Strategy

Implement regular backups of your documentation:

  1. Volume Backups: Schedule regular backups of the /doc directory:
backup-docat.sh
#!/bin/bash
BACKUP_DIR="/backups/docat_$(date +%Y%m%d_%H%M%S)"
mkdir -p $BACKUP_DIR
# Backup documentation
tar -czf $BACKUP_DIR/docs.tar.gz /doc
# Backup configuration
cp upload_tokens.json $BACKUP_DIR/
# Keep only last 30 days
find /backups -name "docat_*" -mtime +30 -delete
  1. Automated Backups: Use cron or scheduled tasks:
Terminal window
# Add to crontab
0 2 * * * /usr/local/bin/backup-docat.sh
  1. Off-site Backups: Upload backups to cloud storage:
Terminal window
# Upload to S3
aws s3 cp $BACKUP_DIR/docs.tar.gz s3://my-bucket/docat-backups/
# Or use rclone for other providers
rclone copy $BACKUP_DIR remote:docat-backups/

Performance Optimization

  1. Nginx Caching: Enable caching for static assets:
location /doc/ {
alias /doc/;
# Enable caching
expires 1h;
add_header Cache-Control "public, immutable";
# Compression
gzip_static on;
}
  1. Client-Side Caching: Set appropriate cache headers:
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
  1. Enable HTTP/2: Nginx with HTTP/2 (handled by Klutch.sh):
listen 443 ssl http2;
  1. Precompression: Precompress large files:
Terminal window
# Find and compress HTML/CSS/JS files
find /doc -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) -exec gzip -k {} \;

Monitoring and Logging

  1. Access Logs: Monitor documentation access:
Terminal window
# View recent access
tail -f /var/log/nginx/access.log
# Most accessed documentation
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
  1. Error Logs: Track errors:
Terminal window
# View errors
tail -f /var/log/nginx/error.log
# Count error types
grep "error" /var/log/nginx/error.log | cut -d' ' -f9- | sort | uniq -c | sort -rn
  1. Upload Monitoring: Track documentation uploads:
Terminal window
# Monitor API logs
tail -f /var/log/docat/docat.out.log | grep "upload"
  1. Disk Usage Monitoring: Track storage consumption:
Terminal window
# Check documentation storage
du -sh /doc/*
# Alert if storage exceeds threshold
USAGE=$(df /doc | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $USAGE -gt 80 ]; then
echo "Warning: Storage usage is ${USAGE}%"
fi
  1. Health Check Script:
health-check.sh
#!/bin/bash
DOCAT_URL="https://your-app.klutch.sh"
# Check main page
if ! curl -f -s -o /dev/null $DOCAT_URL; then
echo "ERROR: DOCAT is not responding"
exit 1
fi
# Check API
if ! curl -f -s -o /dev/null $DOCAT_URL/api/projects; then
echo "ERROR: DOCAT API is not responding"
exit 1
fi
echo "OK: DOCAT is healthy"
exit 0

Resource Allocation

Recommended resources based on usage:

Small Team (1-10 projects):

  • Memory: 512MB - 1GB
  • CPU: 0.5 - 1 vCPU
  • Storage: 10GB - 20GB

Medium Team (10-50 projects):

  • Memory: 1GB - 2GB
  • CPU: 1 - 2 vCPU
  • Storage: 20GB - 50GB

Large Organization (50+ projects):

  • Memory: 2GB - 4GB
  • CPU: 2 - 4 vCPU
  • Storage: 50GB - 200GB

Documentation Organization

  1. Naming Conventions: Use consistent project names:
Terminal window
# Good naming
my-project
api-server
web-app-frontend
# Avoid spaces and special characters
  1. Version Naming: Follow semantic versioning:
Terminal window
# Releases
1.0.0, 1.1.0, 2.0.0
# Pre-releases
1.0.0-beta, 2.0.0-rc1
# Branches
feature-new-api, develop, staging
# Special versions
latest, stable, edge
  1. Project Structure: Organize related projects:
/doc
├── backend-api/
│ ├── 1.0.0/
│ ├── 2.0.0/
│ └── latest/
├── frontend-web/
│ ├── 1.0.0/
│ └── latest/
└── mobile-app/
├── 1.0.0/
└── latest/

Troubleshooting

Cannot Upload Documentation

Symptoms: Upload requests fail with 401 or 403 errors

Solutions:

  1. Verify Upload Token:
Terminal window
# Test token
curl -X POST https://your-app.klutch.sh/api/project/test/1.0.0 \
-H "Docat-Api-Key: your-token" \
-F "file=@docs.tar.gz" -v
  1. Check Token Configuration:
Terminal window
# Verify environment variable is set
echo $DOCAT_UPLOAD_TOKEN
# Check token in upload_tokens.json
cat upload_tokens.json
  1. Verify Archive Format:
Terminal window
# Archive must be tar.gz or zip
file docs.tar.gz
# Output should show: gzip compressed data
# Test archive extraction
tar -tzf docs.tar.gz | head
  1. Check File Size:
Terminal window
# Verify file isn't too large (default limit: 100MB)
ls -lh docs.tar.gz
# Increase Nginx limit if needed in nginx.conf:
# client_max_body_size 500M;

Documentation Not Displaying

Symptoms: Uploaded documentation returns 404 or blank pages

Solutions:

  1. Verify Upload Success:
Terminal window
# List all projects
curl https://your-app.klutch.sh/api/projects
# Check specific project versions
curl https://your-app.klutch.sh/api/project/my-project
  1. Check File Permissions:
Terminal window
# Inside container
ls -la /doc/my-project/1.0.0/
# Fix permissions if needed
chown -R nginx:nginx /doc
  1. Verify index.html Exists:
Terminal window
# Check for index file
ls /doc/my-project/1.0.0/index.html
# Archive must contain index.html at root
tar -tzf docs.tar.gz | grep index.html
  1. Check Nginx Logs:
Terminal window
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/access.log

Version Selector Not Working

Symptoms: Cannot switch between documentation versions

Solutions:

  1. Verify Multiple Versions Exist:
Terminal window
curl https://your-app.klutch.sh/api/project/my-project
# Should show multiple versions
  1. Check Frontend Loading:
Terminal window
# Verify frontend assets are loading
curl https://your-app.klutch.sh/
# Should return HTML with DOCAT interface
  1. Browser Console: Check for JavaScript errors in browser console

  2. Clear Browser Cache: Force refresh with Ctrl+Shift+R (or Cmd+Shift+R on Mac)

High Storage Usage

Symptoms: Running out of disk space, slow performance

Solutions:

  1. Check Storage Usage:
Terminal window
# Total usage
du -sh /doc
# Per project
du -sh /doc/* | sort -h
# Per version
du -sh /doc/my-project/*
  1. Delete Old Versions:
Terminal window
# Delete specific version
curl -X DELETE https://your-app.klutch.sh/api/project/my-project/old-version \
-H "Docat-Api-Key: your-token"
# Script to delete old versions
#!/bin/bash
PROJECT="my-project"
KEEP_VERSIONS=5
# List versions, skip latest N, delete rest
curl -s https://your-app.klutch.sh/api/project/$PROJECT | \
jq -r '.versions[]' | \
tail -n +$((KEEP_VERSIONS + 1)) | \
while read VERSION; do
curl -X DELETE https://your-app.klutch.sh/api/project/$PROJECT/$VERSION \
-H "Docat-Api-Key: your-token"
done
  1. Compress Documentation:
Terminal window
# Enable gzip compression in Nginx
# Already configured in provided nginx.conf
  1. Increase Volume Size: Expand storage in Klutch.sh dashboard

API Not Responding

Symptoms: API requests timeout or return errors

Solutions:

  1. Check API Process:
Terminal window
# Verify API is running
ps aux | grep docat
# Check API logs
tail -f /var/log/docat/docat.err.log
  1. Restart Services:
Terminal window
# Restart supervisor
supervisorctl restart docat
# Or restart entire container
docker restart container_id
  1. Check Port Binding:
Terminal window
# Verify API is listening
netstat -tlnp | grep 5000
  1. Test API Directly:
Terminal window
# Test from inside container
curl http://localhost:5000/projects

Advanced Configuration

Custom Branding

Customize DOCAT’s appearance:

  1. Custom Logo: Replace the default logo:
# In Dockerfile
COPY logo.png /var/www/html/static/logo.png
  1. Custom Styling: Add custom CSS:
custom.css
:root {
--primary-color: #007bff;
--background-color: #f8f9fa;
--text-color: #333;
}
.header {
background-color: var(--primary-color);
}
.project-card {
border: 1px solid var(--primary-color);
}

Include in Nginx configuration:

location /custom.css {
alias /var/www/html/custom.css;
}
  1. Custom Title: Modify HTML:
index.html
<title>Your Company Docs</title>

Search Integration

Enable full-text search across documentation:

  1. Install Search Plugin (if using Sphinx):
conf.py
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinxcontrib.serializinghtml',
]
html_theme = 'sphinx_rtd_theme'
  1. Index Documentation:
Terminal window
# Use Elasticsearch or similar
# Configure search backend
  1. Search API Endpoint: Add custom search endpoint

Access Control

Implement authentication for private documentation:

  1. Basic Auth with Nginx:
location /doc/private-project/ {
alias /doc/private-project/;
auth_basic "Restricted Documentation";
auth_basic_user_file /etc/nginx/.htpasswd;
}

Create password file:

Terminal window
htpasswd -c /etc/nginx/.htpasswd username
  1. IP Whitelist:
location /api/ {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
proxy_pass http://localhost:5000/;
}
  1. OAuth Integration: Use oauth2-proxy for SSO:
docker-compose.yml
services:
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy:latest
ports:
- "4180:4180"
environment:
OAUTH2_PROXY_PROVIDER: github
OAUTH2_PROXY_CLIENT_ID: your-client-id
OAUTH2_PROXY_CLIENT_SECRET: your-client-secret
OAUTH2_PROXY_COOKIE_SECRET: your-cookie-secret
OAUTH2_PROXY_UPSTREAM: http://docat:80

Webhook Notifications

Send notifications when documentation is uploaded:

  1. Create Webhook Handler:
webhook.py
import requests
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def handle_upload():
data = request.json
project = data.get('project')
version = data.get('version')
# Send to Slack
slack_webhook = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
message = {
"text": f"📚 Documentation updated: {project} v{version}",
"username": "DOCAT Bot"
}
requests.post(slack_webhook, json=message)
return {"status": "ok"}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
  1. Configure DOCAT to Call Webhook:
# Modify DOCAT upload handler to trigger webhook

Automated Cleanup

Schedule automated cleanup of old documentation:

  1. Create Cleanup Script:
cleanup-old-docs.sh
#!/bin/bash
DOCAT_URL="https://your-app.klutch.sh"
API_KEY="your-token"
DAYS_TO_KEEP=90
# Find projects
PROJECTS=$(curl -s $DOCAT_URL/api/projects | jq -r '.projects[].name')
for PROJECT in $PROJECTS; do
echo "Checking project: $PROJECT"
# Get versions with timestamps (requires modification to DOCAT API)
VERSIONS=$(curl -s $DOCAT_URL/api/project/$PROJECT | jq -r '.versions[]')
for VERSION in $VERSIONS; do
# Skip 'latest' and semantic versions
if [[ "$VERSION" == "latest" ]] || [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
continue
fi
# Check if version is a date-based branch (e.g., 2024-01-15)
if [[ "$VERSION" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
VERSION_DATE=$(date -d "$VERSION" +%s)
CUTOFF_DATE=$(date -d "$DAYS_TO_KEEP days ago" +%s)
if [ $VERSION_DATE -lt $CUTOFF_DATE ]; then
echo "Deleting old version: $PROJECT/$VERSION"
curl -X DELETE $DOCAT_URL/api/project/$PROJECT/$VERSION \
-H "Docat-Api-Key: $API_KEY"
fi
fi
done
done
  1. Schedule with Cron:
Terminal window
# Add to crontab - run weekly
0 3 * * 0 /usr/local/bin/cleanup-old-docs.sh

Multi-Language Support

Host documentation in multiple languages:

  1. Language-Specific Projects:
Terminal window
# Upload English docs
curl -X POST https://your-app.klutch.sh/api/project/my-project-en/1.0.0 \
-H "Docat-Api-Key: $TOKEN" -F "file=@docs-en.tar.gz"
# Upload Spanish docs
curl -X POST https://your-app.klutch.sh/api/project/my-project-es/1.0.0 \
-H "Docat-Api-Key: $TOKEN" -F "file=@docs-es.tar.gz"
  1. Language Selector: Add custom frontend to switch languages

API Extensions

Extend DOCAT API with custom endpoints:

custom_api.py
from flask import Flask, jsonify
import os
app = Flask(__name__)
@app.route('/api/stats')
def stats():
"""Return documentation statistics"""
doc_path = '/doc'
stats = {
'total_projects': len(os.listdir(doc_path)),
'total_size_mb': sum(
os.path.getsize(os.path.join(dirpath, filename))
for dirpath, _, filenames in os.walk(doc_path)
for filename in filenames
) / (1024 * 1024)
}
return jsonify(stats)
@app.route('/api/health')
def health():
"""Health check endpoint"""
return jsonify({'status': 'healthy', 'version': '1.0.0'})

Additional Resources

Conclusion

DOCAT provides a straightforward, efficient solution for hosting versioned documentation. By deploying on Klutch.sh, you benefit from automatic HTTPS, persistent storage, and simple Docker-based deployment without the complexity of managing servers or dealing with complicated hosting configurations.

The platform’s simplicity is its strength—it does one thing and does it well. With easy API integration, support for multiple documentation formats, and seamless CI/CD integration, DOCAT fits naturally into modern development workflows. Whether you’re documenting a single open-source project or managing documentation for dozens of enterprise applications, DOCAT scales to meet your needs.

The version management system makes it easy to maintain documentation for multiple releases, while the clean interface ensures users can quickly find the information they need. Integration with popular documentation generators like Sphinx, MkDocs, and JSDoc means you can continue using your preferred tools while centralizing documentation hosting.

Start with the basic configuration outlined in this guide, then expand functionality through custom branding, search integration, or access controls as your documentation needs grow. Your documentation remains under your control, deployment is automated through CI/CD pipelines, and the lightweight design ensures fast page loads and minimal hosting costs.

Deploy DOCAT today and provide your team and users with a centralized, version-aware documentation hub that makes finding the right information effortless.